#include "Maze.h"
#include "ScreenManager.h"
#include "DX11ErrorReport.h"
#include "Factory.h"
#include "Text.h"
#include "ConfigManager.h"
#include "Timer.h"
#include "MiniMap.h"
#include "CameraManager.h"
#include "DX11HelpfulFunctions.h"
#include "Get3DMousePos.h"
#include "NodePriorityQueue.h"
#include "DX11TextureManager.h"
#include "Agent.h"

#include <algorithm>
#include <time.h>

Maze::Maze()
{
	//m_pVertexBufferSouth = nullptr;
	//m_pIndexBufferSouth = nullptr;
	//m_pConstantBufferSouth = nullptr;
	//m_pVertexBufferWest = nullptr;
	//m_pIndexBufferWest = nullptr;
	//m_pConstantBufferWest = nullptr;

	D3DXMatrixIdentity(&m_world);
	D3DXMatrixIdentity(&m_worldSouth);
	D3DXMatrixIdentity(&m_worldWest);
	
	m_seed = TheConfigManager::Instance()->GetSeed();
	//m_seed = 1365775786;
	srand(m_seed);
	m_displayInfo.timeToGenerate = 0.0f;

	
	m_canCheckForPick = false;
	m_mouseX = -1;
	m_mouseY = -1;
	m_pickedColour = D3DXVECTOR4(-1, -1, -1, -1);
	m_roomColours.push_back(D3DXVECTOR4(1.0f, 0.0f, 0.0f, 1.0f));
	m_roomColours.push_back(D3DXVECTOR4(0.0f, 1.0f, 0.0f, 1.0f));
	m_roomColours.push_back(D3DXVECTOR4(0.0f, 0.0f, 1.0f, 1.0f));

	m_roomColours.push_back(D3DXVECTOR4(1.0f, 1.0f, 0.0f, 1.0f));
	m_roomColours.push_back(D3DXVECTOR4(0.0f, 1.0f, 1.0f, 1.0f));
	m_roomColours.push_back(D3DXVECTOR4(1.0f, 0.0f, 1.0f, 1.0f));

	m_miniMapElesScale = D3DXVECTOR3(1.0f, 1.0f, 1.0f);

	TheEventPoller::Instance()->AddHandler(this);
}

Maze::~Maze()
{
	m_grid.clear();
	TheEventPoller::Instance()->RemoveHandler(this);
	//if (m_pVertexBufferSouth) m_pVertexBufferSouth->Release();
	//if (m_pIndexBufferSouth) m_pIndexBufferSouth->Release();
	//if (m_pConstantBufferSouth) m_pConstantBufferSouth->Release();
	//if (m_pVertexBufferWest) m_pVertexBufferWest->Release();
	//if (m_pIndexBufferWest) m_pIndexBufferWest->Release();
	//if (m_pConstantBufferWest) m_pConstantBufferWest->Release();
}

std::vector<CellPosition> cellsVisited;

bool Maze::Generate(int numOfRooms, const D3DXVECTOR2& size, const D3DXVECTOR3& cellSize)
{
	int currentID = 0;
	int numOfCells = int(size.x) * int(size.y);
	//m_seed = rand();
	//srand(m_seed);
	CellPosition currentCell = CellPosition(0, 0);
	CellPosition start = CellPosition(0, 0);
	m_gridSize = size;
	m_size = D3DXVECTOR3(size.x * cellSize.x, cellSize.y, size.y * cellSize.z);
	m_position = D3DXVECTOR3(cellSize.x * -size.x * 0.5f, 0.0f, cellSize.z * -size.y * 0.5f);

	for (int x = 0; x != size.x; x++)
	{
		currentCell.first = x;
		for (int y = 0; y != size.y; y++)
		{
			currentCell.second = y;
			m_grid[currentCell] = Cell();
			m_grid[currentCell].SetPos(D3DXVECTOR3((float)x * 10.0f, 0.0f, (float)y * 10.0f));
		}
	}

	// set cell position type top/bot/left/right/corner
	currentCell = CellPosition(0, 0);
	for (int x = 0; x != size.x; x++)
	{
		currentCell.first = x;
		//Cell curCell = m_grid[currentCell];
		PositionType curCellPType;// = curCell.GetPosType();

		for (int y = 0; y != size.y; y++)
		{
			currentCell.second = y;
			curCellPType = m_grid[currentCell].GetPosType();
			// test if it's top/bot
			// and test if it's corner
			
			// test if it's right/left
			if (x == 0)
			{
				curCellPType = LEFT;
			}
			else if (x == size.x - 1)
			{
				curCellPType = RIGHT;
			}

			if (y == 0)
			{
				curCellPType = PositionType(curCellPType + TOP);
			}
			else if (y == size.y - 1)
			{
				curCellPType = PositionType(curCellPType + BOT);
			}

			if (curCellPType == NO_TYPE)
			{
				curCellPType = CENTRE;
			}
			m_grid[currentCell].SetPosType(curCellPType);
		}
	}

	//GenerateDFS(start);

	// set maze edges	
	for (int i = 0; i != m_gridSize.x; i++)
	{
		m_grid[CellPosition(i, 0)].SetVisited(true);
		m_grid[CellPosition(i, (int)m_gridSize.y - 1)].SetVisited(true);

		m_grid[CellPosition(i, 0)].SetCellType(EDGE);
		m_grid[CellPosition(i, (int)m_gridSize.y - 1)].SetCellType(EDGE);
	}
	for (int i = 0; i != m_gridSize.y; i++)
	{
		m_grid[CellPosition(0, i)].SetVisited(true);
		m_grid[CellPosition((int)m_gridSize.x - 1, i)].SetVisited(true);

		m_grid[CellPosition(0, i)].SetCellType(EDGE);
		m_grid[CellPosition((int)m_gridSize.x - 1, i)].SetCellType(EDGE);
	}


	// generate rooms: start
	int numOfAvailableCells = ((int)size.x - 2) * ((int)size.y - 2);
	//m_sizeOfRooms[0] = RoomSize(2, 2);
	//m_sizeOfRooms[1] = RoomSize(2, 2);
	//m_sizeOfRooms[2] = RoomSize(3, 2);
	std::vector<CellPosition> checkedCells;
	for (int i = 0; i != m_numOfRooms; i++)
	{
		while (true)
		{
			int randX;// = rand() % ((int)size.x - 3);
			int randY;// = rand() % ((int)size.y - 3);

			bool xTrue = false;
			bool yTrue = false;
			while (!xTrue || !yTrue)
			{
				randX = rand() % ((int)size.x - 5);
				randY = rand() % ((int)size.y - 5);

				if (randX % 2 == 0)
				{
					xTrue = true;
				}
				if (randY % 2 == 0)
				{
					yTrue = true;
				}
			}

			CellPosition randStartCell = CellPosition(randX + 3, randY + 3);
			
			std::vector<CellPosition>::iterator checkedCellsIt = std::find(checkedCells.begin(),
																			checkedCells.end(),
																			randStartCell);

			if (checkedCellsIt == checkedCells.end())
			{
				checkedCells.push_back(randStartCell);
				m_roomsCells[i].clear();
				std::stack<CellPosition> currentRoomsCells;
				std::vector<CellPosition> toCheckRoomCells;
				bool cellIsRoom = false;

				if (!m_grid[randStartCell].GetIsRoom() && !m_grid[randStartCell].GetVisited())
				{
					//currentRoomsCells.push(randStartCell);
					int curSizeOfRoom = 1;

					CellPosition curCell = randStartCell; // room top left
					CellPosition farNorthCell = CellPosition(curCell.first, curCell.second - m_sizeOfRooms[i].second - 1);
					CellPosition farSouthCell = CellPosition(curCell.first, curCell.second + m_sizeOfRooms[i].second + 1);
					CellPosition farEastCell = CellPosition(curCell.first + m_sizeOfRooms[i].first + 1, curCell.second);
					CellPosition farWestCell = CellPosition(curCell.first - m_sizeOfRooms[i].first - 1, curCell.second);

					//while (!cellIsRoom)
					//{
					CellPosition nextCell = curCell;
					for (int a = 0; a != m_sizeOfRooms[i].first; a++)
					{
						for (int b = 0; b != m_sizeOfRooms[i].second; b++)
						{
							currentRoomsCells.push(nextCell);
							toCheckRoomCells.push_back(nextCell);
							Grid::iterator it = m_grid.find(nextCell);
							if (it != m_grid.end())
							{
								if (m_grid[nextCell].GetIsRoom() || m_grid[nextCell].GetVisited())
								{
									// this cell is a room so can't use this
									// set notfoundroom to false
									cellIsRoom = true;
									break;
								}
							}
							else
							{
								// next cell is out of the grid so end here
								cellIsRoom = true;
								break;
							}
							nextCell.second++;
						}
						nextCell.second = curCell.second;
						nextCell.first++;
					}
					//break;
					//}
				}
				else
				{
					cellIsRoom = true;
				}
				// if cellIsRoom == true
				// then a room was not found so need to check different cell
				// if it's not a room then this cell stack is a room
				if (!cellIsRoom)
				{
					bool badRoomPos = false;
					std::vector<CellPosition>::iterator it;
					for (int j = 0; j != toCheckRoomCells.size(); j++)
					{
						CellPosition currentPos = toCheckRoomCells[j];
						CellPosition north = CellPosition(currentCell.first, currentCell.second - 1);
						CellPosition east = CellPosition(currentCell.first + 1, currentCell.second);
						CellPosition south = CellPosition(currentCell.first, currentCell.second + 1);
						CellPosition west = CellPosition(currentCell.first - 1, currentCell.second);

						if (m_grid[north].GetCellType() == ROOM)
						{
							it = std::find(toCheckRoomCells.begin(), toCheckRoomCells.end(), north);
							if (it == toCheckRoomCells.end())
							{
								badRoomPos = true;
								continue;
							}
						}
						if (m_grid[east].GetCellType() == ROOM)
						{
							it = std::find(toCheckRoomCells.begin(), toCheckRoomCells.end(), east);
							if (it == toCheckRoomCells.end())
							{
								badRoomPos = true;
								continue;
							}
						}
						if (m_grid[south].GetCellType() == ROOM)
						{
							it = std::find(toCheckRoomCells.begin(), toCheckRoomCells.end(), south);
							if (it == toCheckRoomCells.end())
							{
								badRoomPos = true;
								continue;
							}
						}
						if (m_grid[west].GetCellType() == ROOM)
						{
							it = std::find(toCheckRoomCells.begin(), toCheckRoomCells.end(), west);
							if (it == toCheckRoomCells.end())
							{
								badRoomPos = true;
								continue;
							}
						}
					}
					if (!badRoomPos)
					{
						while (!currentRoomsCells.empty())
						{
							m_grid[currentRoomsCells.top()].SetIsRoom(true);
							m_grid[currentRoomsCells.top()].SetVisited(true);
							m_roomsCells[i].push_back(currentRoomsCells.top());
							m_grid[currentRoomsCells.top()].SetCellType(ROOM);
							currentRoomsCells.pop();
						}
						break;
					}
				}
				if (checkedCells.size() >= (unsigned int)numOfAvailableCells)
				{
					break;
				}
			}
		}
	}
	// generate surrounding rooms cells: start
	// m_surroundingRoomsCells

	int j = 0;
	for (int i = 0; i != m_roomsCells.size(); i++)
	{
		CellPosition TOP_LEFT = m_roomsCells[i][j];
		CellPosition BOT_RIGHT = m_roomsCells[i][j];

		for (; j != m_roomsCells[i].size(); j++)
		{
			//m_surroundingRoomsCells[i].pu
			CellPosition currentCell = m_roomsCells[i][j];

			if (currentCell.first < TOP_LEFT.first)
			{
				TOP_LEFT.first = currentCell.first;
			}
			if (currentCell.first > BOT_RIGHT.first)
			{
				BOT_RIGHT.first = currentCell.first;
			}
			if (currentCell.second < TOP_LEFT.second)
			{
				TOP_LEFT.second = currentCell.second;
			}
			if (currentCell.second > BOT_RIGHT.second)
			{
				BOT_RIGHT.second = currentCell.second;
			}
		}
		// have top left + bot right of the room
		// CellPosition currentCell = TOP_LEFT;
		CellPosition top = TOP_LEFT;
		top.first++;
		top.second--;
		//m_surroundingRoomsCells[i].push_back(top);
		CellPosition left = TOP_LEFT;
		left.first--;
		left.second++;
		//m_surroundingRoomsCells[i].push_back(left);
		CellPosition right = BOT_RIGHT;
		right.first++;
		right.second--;
		//m_surroundingRoomsCells[i].push_back(right);
		CellPosition bot = BOT_RIGHT;
		bot.first--;
		bot.second++;
		//m_surroundingRoomsCells[i].push_back(bot);

		for (int x = 0; x != m_sizeOfRooms[i].first - 2; x++)
		{

			m_surroundingRoomsCells[i].push_back(top);
			m_surroundingRoomsCells[i].push_back(bot);
			top.first++;
			bot.first--;
		}
		for (int y = 0; y != m_sizeOfRooms[i].second - 2; y++)
		{
			
			m_surroundingRoomsCells[i].push_back(left);
			m_surroundingRoomsCells[i].push_back(right);
			left.second++;
			right.second--;
		}

		//bool top = false;
		//bool bot = false;
		//bool left = false;
		//bool right = false;

		//while (!top || !bot || !left || !right)
		//{
		//	if (tempTop.first < BOT_RIGHT.first)
		//	{
		//		tempTop.first++;
		//		m_surroundingRoomsCells[i].push_back(tempTop);
		//	}
		//	else
		//	{
		//		top = true;
		//	}
		//	if (tempLeft.second < BOT_RIGHT.second)
		//	{
		//		tempLeft.second++;
		//		m_surroundingRoomsCells[i].push_back(tempLeft);
		//	}
		//	else
		//	{
		//		left = true;
		//	}
		//	if (tempBot.first > TOP_LEFT.first)
		//	{
		//		tempBot.first--;
		//		m_surroundingRoomsCells[i].push_back(tempBot);
		//	}
		//	else
		//	{
		//		bot = true;
		//	}
		//	if (tempRight.second > TOP_LEFT.second)
		//	{
		//		tempRight.second--;
		//		m_surroundingRoomsCells[i].push_back(tempRight);
		//	}
		//	else
		//	{
		//		right = true;
		//	}
		//}

		j = 0;
	}

	// generate surrounding rooms cells: end
	
	//for (int i = 0; i != m_surroundingRoomsCells.size(); i++)
	//{
	//	for (int j = 0; j != m_surroundingRoomsCells[i].size(); j++)
	//	{
	//		m_grid[m_surroundingRoomsCells[i][j]].SetCellType(WALL);
	//	}
	//}

	// calculate room corners
	for (int i = 0; i != m_roomsCells.size(); i++)
	{
		CellPosition topLeft(65536, 65536);
		CellPosition topRight;
		CellPosition botRight(-1, -1);
		CellPosition botLeft;

		for (int j = 0; j != m_roomsCells[i].size(); j++)
		{
			CellPosition curCell = m_roomsCells[i][j];

			if (topLeft.first > curCell.first)
			{
				topLeft.first = curCell.first;
			}
			if (topLeft.second > curCell.second)
			{
				topLeft.second = curCell.second;
			}
			if (botRight.first < curCell.first)
			{
				botRight.first = curCell.first;
			}
			if (botRight.second < curCell.second)
			{
				botRight.second = curCell.second;
			}
		}

		topRight = topLeft;
		botLeft = botRight;

		topRight.first += m_sizeOfRooms[i].first - 1;
		botLeft.first -= m_sizeOfRooms[i].first - 1;

		m_grid[topLeft].SetCellType(ROOM_CORNER);
		m_grid[topLeft].SetVisited(true);
		m_grid[topRight].SetCellType(ROOM_CORNER);
		m_grid[topRight].SetVisited(true);
		m_grid[botLeft].SetCellType(ROOM_CORNER);
		m_grid[botLeft].SetVisited(true);
		m_grid[botRight].SetCellType(ROOM_CORNER);
		m_grid[botRight].SetVisited(true);
	}

	// calculate actual room cells from m_roomsCells;
	for (int i = 0; i != m_roomsCells.size(); i++)
	{
		// find the corners
		CellPosition topLeft((int)m_gridSize.x, (int)m_gridSize.y);
		CellPosition botRight(0, 0);
		for (int j = 0; j != m_roomsCells[i].size(); j++)
		{
			if (m_roomsCells[i][j].first < topLeft.first)
			{
				topLeft.first = m_roomsCells[i][j].first;
			}
			if (m_roomsCells[i][j].second < topLeft.second)
			{
				topLeft.second = m_roomsCells[i][j].second;
			}

			if (m_roomsCells[i][j].first > botRight.first)
			{
				botRight.first = m_roomsCells[i][j].first;
			}
			if (m_roomsCells[i][j].second > botRight.second)
			{
				botRight.second = m_roomsCells[i][j].second;
			}
		}
		CellPosition cell = topLeft;
		for (int x = 1; x != m_sizeOfRooms[i].first - 1; x++)
		{
			cell.first++;
			for (int y = 1; y != m_sizeOfRooms[i].second - 1; y++)
			{
				cell.second++;
				m_roomCells[i].push_back(cell);
			}
			cell.second = topLeft.second;
		}
	}

	// generate rooms: end
	

	// first = first room, second = the second connected room


	// generate paths between the rooms
	//for (int i = 0; i != m_connectingRooms.size(); i++)
	//{
	//	CellPosition startCell;
	//	CellPosition endCell;
	//	{
	//		// find start cell: start
	//		std::vector<CellPosition> availableWalls;
	//		std::vector<CellPosition> visitedCells;
	//		while (true)
	//		{
	//			availableWalls.clear();
	//			int randCell;
	//			CellPosition selectedRandCell;
	//			std::vector<CellPosition>::iterator visitedCellsIt;
	//			// find a cell that hasn't yet been visited
	//			while (true)
	//			{	
	//				randCell = rand() % m_roomsCells[m_connectingRooms[i].first].size();
	//				selectedRandCell = m_roomsCells[m_connectingRooms[i].first][randCell];
	//				visitedCellsIt = std::find(visitedCells.begin(), visitedCells.end(), selectedRandCell);
	//				if (visitedCellsIt == visitedCells.end())
	//				{
	//					visitedCells.push_back(selectedRandCell);
	//					break;
	//				}
	//			}

	//			CellPosition curCell = selectedRandCell;
	//			CellPosition northCell = CellPosition(curCell.first, curCell.second - 1);
	//			CellPosition eastCell = CellPosition(curCell.first + 1, curCell.second);
	//			CellPosition southCell = CellPosition(curCell.first, curCell.second + 1);
	//			CellPosition westCell = CellPosition(curCell.first - 1, curCell.second);

	//			if (!m_grid[northCell].GetVisited() && !m_grid[northCell].GetIsRoom())
	//			{
	//				availableWalls.push_back(northCell);
	//			}
	//			if (!m_grid[eastCell].GetVisited() && !m_grid[eastCell].GetIsRoom())
	//			{
	//				availableWalls.push_back(eastCell);
	//			}
	//			if (!m_grid[southCell].GetVisited() && !m_grid[southCell].GetIsRoom())
	//			{
	//				availableWalls.push_back(southCell);
	//			}
	//			if (!m_grid[westCell].GetVisited() && !m_grid[westCell].GetIsRoom())
	//			{
	//				availableWalls.push_back(westCell);
	//			}

	//			if (availableWalls.size() != 0)
	//			{
	//				break;
	//			}
	//		}
	//		int nextRandCell = rand() % availableWalls.size();
	//		startCell = availableWalls[nextRandCell];
	//		// find start cell: end

	//		// find end cell: start
	//		availableWalls.clear();
	//		while (true)
	//		{
	//			availableWalls.clear();
	//			int randCell;
	//			CellPosition selectedRandCell;
	//			std::vector<CellPosition>::iterator visitedCellsIt;
	//			// find a cell that hasn't yet been visited
	//			while (true)
	//			{	
	//				randCell = rand() % m_roomsCells[m_connectingRooms[i].second].size();
	//				selectedRandCell = m_roomsCells[m_connectingRooms[i].second][randCell];
	//				visitedCellsIt = std::find(visitedCells.begin(), visitedCells.end(), selectedRandCell);
	//				if (visitedCellsIt == visitedCells.end())
	//				{
	//					visitedCells.push_back(selectedRandCell);
	//					break;
	//				}
	//			}

	//			CellPosition curCell = selectedRandCell;
	//			CellPosition northCell = CellPosition(curCell.first, curCell.second - 1);
	//			CellPosition eastCell = CellPosition(curCell.first + 1, curCell.second);
	//			CellPosition southCell = CellPosition(curCell.first, curCell.second + 1);
	//			CellPosition westCell = CellPosition(curCell.first - 1, curCell.second);

	//			if (!m_grid[northCell].GetVisited() && !m_grid[northCell].GetIsRoom())
	//			{
	//				availableWalls.push_back(northCell);
	//			}
	//			if (!m_grid[eastCell].GetVisited() && !m_grid[eastCell].GetIsRoom())
	//			{
	//				availableWalls.push_back(eastCell);
	//			}
	//			if (!m_grid[southCell].GetVisited() && !m_grid[southCell].GetIsRoom())
	//			{
	//				availableWalls.push_back(southCell);
	//			}
	//			if (!m_grid[westCell].GetVisited() && !m_grid[westCell].GetIsRoom())
	//			{
	//				availableWalls.push_back(westCell);
	//			}

	//			if (availableWalls.size() != 0)
	//			{
	//				break;
	//			}
	//		}
	//		nextRandCell = rand() % availableWalls.size();
	//		endCell = availableWalls[nextRandCell];
	//		// find end cell: end
	//	}
	//}

	
	// calculate room edges
	CalculateRoomEdges();
	GeneratePathsDFS();


	// find find positions of the wall relative to the position of the cell
	// cell position in 3d space
	m_cellSize = D3DXVECTOR3(m_size.x / size.x, 10.0f, m_size.z / size.y);
	for (int i = 0; i != size.x; i++)
	{
		for (int j = 0; j != size.y; j++)
		{
			D3DXVECTOR3 cellPos = D3DXVECTOR3((i) * m_cellSize.x,  m_cellSize.y * 0.5f, (j) * m_cellSize.z);
			m_grid[CellPosition(i, j)].SetPos(cellPos);
			m_grid[CellPosition(i, j)].GetOOBB().centre = D3DXVECTOR3(cellPos.x, m_cellSize.y * 1.5f, cellPos.z);
			m_grid[CellPosition(i, j)].GetOOBB().extents[0] = m_cellSize.x * 0.5f;
			m_grid[CellPosition(i, j)].GetOOBB().extents[1] = m_cellSize.y * 0.5f;
			m_grid[CellPosition(i, j)].GetOOBB().extents[2] = m_cellSize.z * 0.5f;

			// set south wall pos
			m_grid[CellPosition(i, j)].SetSouthWallPosition(D3DXVECTOR3(cellPos.x , 0.0f, cellPos.z + (m_cellSize.z * 0.5f)));

			// set west wall pos
			m_grid[CellPosition(i, j)].SetWestWallPosition(D3DXVECTOR3(cellPos.x + (m_cellSize.x * 0.5f), 0.0f, cellPos.z));

			// north wall
			m_grid[CellPosition(i, j)].SetNorthWallPosition(D3DXVECTOR3(cellPos.x , 0.0f, cellPos.z - (m_cellSize.z * 0.5f)));

			// east wall
			m_grid[CellPosition(i, j)].SetEastWallPosition(D3DXVECTOR3(cellPos.x - (m_cellSize.x * 0.5f), 0.0f, cellPos.z));
		}
	}

	// setup cell colours
	//float numOfNonEmptyAndEdgeCells = 0;

	//// find how many non empty + edge cells there are for colour step
	//for (Grid::iterator it = m_grid.begin(); it != m_grid.end(); ++it)
	//{
	//	if (it->second.GetCellType() != EMPTY && it->second.GetCellType() != EDGE)
	//	{
	//		numOfNonEmptyAndEdgeCells++;
	//	}
	//}
	

	CalculateWallCells();
	
	// calculate door cells
	CalculateDoorCells();

	// calculate mini map draw cells
	// only paths and room cells
	for (Grid::iterator it = m_grid.begin(); it != m_grid.end(); ++it)
	{
		//if (it->second.GetCellType() == ROOM || it->second.GetCellType() == PATH ||
		//	it->second.GetCellType() == HORIZONTAL_DOOR || it->second.GetCellType() == VERTICAL_DOOR)
		//{
		//	m_miniMapDrawCells.push_back(it->first);
		//}
		if (it->second.GetCellType() == PATH || it->second.GetCellType() == ROOM ||
			 it->second.GetCellType() == VERTICAL_DOOR ||  it->second.GetCellType() == HORIZONTAL_DOOR)
		{
			m_miniMapDrawCells.push_back(it->first);
		}
	}

	// set m_cellColours
	
	//int numOfCells = m_gridSize.x * m_gridSize.y;
	int cellCount = 0;

	std::vector<D3DXVECTOR4> colours;
	float curR = 0;
	float curG = 0;
	float curB = 0;

	float colStep = 1.0f / 255.0f;
	bool canBreak = false;
	for (int r = 0; r <= 255; r += 1)
	{
		//curG = 0;
		for (int g = 0; g <= 255; g += 1)
		{
			//curB = 0;
			for (int b = 0; b <= 255; b += 1)
			{
				//colours.push_back(D3DXVECTOR4(curR, curG, curB, 1.0f));
				cellCount++;
				colours.push_back(D3DXVECTOR4((float)r, (float)g, (float)b, 1.0f));

				if (cellCount >= m_grid.size())
				{
					canBreak = true;
					break;
				}
			}
			if (canBreak)
			{
				break;
			}
			//curG += colStep;
		}
		if (canBreak)
		{
			break;
		}
		//curR += colStep;
	}

	for (int i = 0; i != m_miniMapDrawCells.size(); i++)
	{
		m_cellColours[colours[i]] = m_miniMapDrawCells[i];
		m_cellColoursOp[m_miniMapDrawCells[i]] = colours[i];
	}

	// calc path/wall cells
	CalculateToDrawPaths();
	CalculateToDrawWalls();

	colours.clear();

	return true;
}

void Maze::GeneratePathsDFS()
{	
	CellPosition startCell;
	std::vector<CellPosition> cellsWithPaths;
	std::map<CellPosition, std::vector<CellPosition>> startAndEndCells;

	for (int i = 0; i != m_connectingRooms.size(); i++)
	{
		std::vector<CellPosition>::iterator roomsCellsBegItFirst = m_surroundingRoomsCells[m_connectingRooms[i].first].begin();
		std::vector<CellPosition>::iterator roomsCellsEndItFirst = m_surroundingRoomsCells[m_connectingRooms[i].first].end();

		std::vector<CellPosition>::iterator roomsCellsBegIt = m_surroundingRoomsCells[m_connectingRooms[i].second].begin();
		std::vector<CellPosition>::iterator roomsCellsEndIt = m_surroundingRoomsCells[m_connectingRooms[i].second].end();
		bool alreadyBeenVisited = false;
		std::stack<CellPosition> pathTaken;
		// test: start
		
		// finds if the path used has already been visited
		for (int p = 0; p != cellsWithPaths.size(); p++)
		{
			CellPosition currentCell = cellsWithPaths[p];
			CellPosition northCell = CellPosition(currentCell.first, currentCell.second - 2);
			CellPosition eastCell = CellPosition(currentCell.first + 2, currentCell.second);
			CellPosition southCell = CellPosition(currentCell.first, currentCell.second + 2);
			CellPosition westCell = CellPosition(currentCell.first - 2, currentCell.second);

			// northCellCon (Con = connecting)
			CellPosition northCellCon = CellPosition(currentCell.first, currentCell.second - 1);
			CellPosition eastCellCon = CellPosition(currentCell.first + 1, currentCell.second);
			CellPosition southCellCon = CellPosition(currentCell.first, currentCell.second + 1);
			CellPosition westCellCon = CellPosition(currentCell.first - 1, currentCell.second);

			std::vector<CellPosition>::iterator checkedCellsIt;
			std::vector<CellPosition>::iterator checkedCellsItFirst; // checking .first rooms cells

			if (m_grid.find(northCell) != m_grid.end())
			{
				checkedCellsIt = std::find(roomsCellsBegIt, roomsCellsEndIt, northCellCon);
				if (checkedCellsIt != roomsCellsEndIt && m_grid[northCellCon].GetCellType() != ROOM &&
					m_grid[northCellCon].GetCellType() != ROOM_CORNER)
				{
					m_grid[startCell].SetCellType(PATH);
					m_grid[northCellCon].SetCellType(PATH);
					startAndEndCells[startCell].push_back(northCellCon);
					m_doorCells.push_back(JoiningDoorCells());
					m_doorCells.back().position[0] = startCell;
					m_doorCells.back().position[1] = northCellCon;
					m_doorCells.back().room[0] = m_connectingRooms[i].first;
					m_doorCells.back().room[1] = m_connectingRooms[i].second;
					alreadyBeenVisited = true;
					break;
				}
			}
			if (m_grid.find(eastCell) != m_grid.end())
			{
				checkedCellsIt = std::find(roomsCellsBegIt, roomsCellsEndIt, eastCellCon);
				if (checkedCellsIt != roomsCellsEndIt && m_grid[eastCellCon].GetCellType() != ROOM &&
					m_grid[eastCellCon].GetCellType() != ROOM_CORNER)
				{
					m_grid[startCell].SetCellType(PATH);
					m_grid[eastCellCon].SetCellType(PATH);
					startAndEndCells[startCell].push_back(eastCellCon);
					m_doorCells.push_back(JoiningDoorCells());
					m_doorCells.back().position[0] = startCell;
					m_doorCells.back().position[1] = eastCellCon;
					m_doorCells.back().room[0] = m_connectingRooms[i].first;
					m_doorCells.back().room[1] = m_connectingRooms[i].second;
					alreadyBeenVisited = true;
					break;
				}
			}
			if (m_grid.find(southCell) != m_grid.end())
			{
				checkedCellsIt = std::find(roomsCellsBegIt, roomsCellsEndIt, southCellCon);
				if (checkedCellsIt != roomsCellsEndIt && m_grid[southCellCon].GetCellType() != ROOM &&
					m_grid[southCellCon].GetCellType() != ROOM_CORNER)
				{
					//checkedCellsItFirst = std::find(roomsCellsBegItFirst, roomsCellsEndItFirst, southCellCon);
					//if (checkedCellsItFirst != roomsCellsEndItFirst)
					//{
						m_grid[startCell].SetCellType(PATH);
						m_grid[southCellCon].SetCellType(PATH);
						startAndEndCells[startCell].push_back(southCellCon);
						m_doorCells.push_back(JoiningDoorCells());
						m_doorCells.back().position[0] = startCell;
						m_doorCells.back().position[1] = southCellCon;
						m_doorCells.back().room[0] = m_connectingRooms[i].first;
						m_doorCells.back().room[1] = m_connectingRooms[i].second;
						alreadyBeenVisited = true;
						break;
					//}
				}
			}
			if (m_grid.find(westCell) != m_grid.end())
			{
				checkedCellsIt = std::find(roomsCellsBegIt, roomsCellsEndIt, westCellCon);
				if (checkedCellsIt != roomsCellsEndIt && m_grid[westCellCon].GetCellType() != ROOM &&
					m_grid[westCellCon].GetCellType() != ROOM_CORNER)
				{
					m_grid[startCell].SetCellType(PATH);
					m_grid[westCellCon].SetCellType(PATH);
					startAndEndCells[startCell].push_back(westCellCon);
					m_doorCells.push_back(JoiningDoorCells());
					m_doorCells.back().position[0] = startCell;
					m_doorCells.back().position[1] = westCellCon;
					m_doorCells.back().room[0] = m_connectingRooms[i].first;
					m_doorCells.back().room[1] = m_connectingRooms[i].second;
					alreadyBeenVisited = true;
					break;
				}
			}

			pathTaken.push(currentCell);
		}

		while(!pathTaken.empty())
		{
			pathTaken.pop();
		}

		// test: end
		if (!alreadyBeenVisited)
		{
			int rCell = rand() % m_surroundingRoomsCells[m_connectingRooms[i].first].size();
			CellPosition currentCell = m_surroundingRoomsCells[m_connectingRooms[i].first][rCell];

			bool xMod2 = false;
			bool yMod2 = false;

			std::map<int, CellPosition> startableCells;
			std::map<int, bool> startableCellsVisited;

			int startableCellsCounter = 0;
			for (int w = 0; w != m_surroundingRoomsCells[m_connectingRooms[i].first].size(); w++)
			{
				xMod2 = false;
				yMod2 = false;
				CellPosition tempCell = m_surroundingRoomsCells[m_connectingRooms[i].first][w];
				if (m_grid[tempCell].GetCellType() != EDGE && m_grid[tempCell].GetCellType() != ROOM &&
					m_grid[tempCell].GetCellType() != ROOM_CORNER && m_grid[tempCell].GetCellType() != PATH &&
					m_grid[tempCell].GetCellType() != ROOM_EDGE)
				{
					if (tempCell.first % 2 == 0)
					{
						xMod2 = true;
					}
					if (tempCell.second % 2 == 0)
					{
						yMod2 = true;
					}
				}

				if ((xMod2) && (yMod2))
				{
					startableCells[startableCellsCounter] = tempCell;
					startableCellsVisited[startableCellsCounter] = false;
					startableCellsCounter++;
				}
			}
			
			bool failedToFindPath = false;
			std::vector<CellPosition>::iterator it;
			bool pathFound = false;
			while (!pathFound)
			{
				std::vector<int> startableCellsVisitable;
				for (int w = 0; w != startableCells.size(); w++)
				{
					if (startableCellsVisited[w] == false)
					{
						startableCellsVisitable.push_back(w);
					}
				}

				if (startableCellsVisitable.size() == 0)
				{
					// no more paths to go to

					//std::wstring wSeedNum = L"Failed to generate maze, seed: ";
					//wSeedNum += ToWString(m_seed);
					failedToFindPath = true;
					//DX11ErrorMsg(wSeedNum.c_str(), L"Maze::GeneratePathsDFS()", MB_OK);
					break;
				}
				else
				{
					int nextStart = rand() % startableCellsVisitable.size();
					currentCell = startableCells[startableCellsVisitable[nextStart]];
					startCell = currentCell;
					startableCellsVisited[startableCellsVisitable[nextStart]] = true;
				}


				CellPosition centreCell = currentCell;

				std::stack<CellPosition> visitedCells;
				std::stack<CellPosition> visitedCellsCon;
				std::vector<CellPosition> availableCells;
				std::vector<CellPosition> availableCellsCon;

				std::vector<CellPosition> foundRoomCells;
				std::vector<CellPosition> foundRoomsCellsCon;

				m_grid[currentCell].SetCellType(PATH);
				visitedCells.push(currentCell);
				visitedCellsCon.push(currentCell);
				cellsWithPaths.push_back(currentCell);
				//pathTaken.push(currentCell);
				//pathTaken.push(centreCell);

				while (!alreadyBeenVisited)
				{
					// check if currentCell is in the next room
					it = std::find(roomsCellsBegIt, roomsCellsEndIt, currentCell);

					if (it != roomsCellsEndIt)
					{
						//if (m_grid[centreCell].GetCellType() != ROOM_CORNER)
						//{
							m_grid[*it].SetCellType(PATH);
							m_grid[startCell].SetCellType(PATH);
							startAndEndCells[startCell].push_back(*it);
							m_doorCells.push_back(JoiningDoorCells());
							m_doorCells.back().position[0] = startCell;
							m_doorCells.back().position[1] = *it;
							m_doorCells.back().room[0] = m_connectingRooms[i].first;
							m_doorCells.back().room[1] = m_connectingRooms[i].second;
							pathFound = true;
						//}
						break;
					}

					it = std::find(roomsCellsBegIt, roomsCellsEndIt, centreCell);

					if (it != roomsCellsEndIt)
					{
						//if (m_grid[centreCell].GetCellType() != ROOM_CORNER)
						//{
							//m_grid[*it].SetCellType(VERTICAL_DOOR);
							//m_doorCells.push_back(*it);
							//m_doorCells.push_back(startCell);
							m_grid[*it].SetCellType(PATH);
							m_grid[startCell].SetCellType(PATH);
							startAndEndCells[startCell].push_back(*it);
							m_doorCells.push_back(JoiningDoorCells());
							m_doorCells.back().position[0] = startCell;
							m_doorCells.back().position[1] = *it;
							m_doorCells.back().room[0] = m_connectingRooms[i].first;
							m_doorCells.back().room[1] = m_connectingRooms[i].second;
							pathFound = true;
							break;
						//}
					}

					CellPosition northCell = CellPosition(currentCell.first, currentCell.second - 2);
					CellPosition eastCell = CellPosition(currentCell.first + 2, currentCell.second);
					CellPosition southCell = CellPosition(currentCell.first, currentCell.second + 2);
					CellPosition westCell = CellPosition(currentCell.first - 2, currentCell.second);

					// northCellCon (Con = connecting)
					CellPosition northCellCon = CellPosition(currentCell.first, currentCell.second - 1);
					CellPosition eastCellCon = CellPosition(currentCell.first + 1, currentCell.second);
					CellPosition southCellCon = CellPosition(currentCell.first, currentCell.second + 1);
					CellPosition westCellCon = CellPosition(currentCell.first - 1, currentCell.second);

					int numOfDirections = 0;

					// check that cells are empty
					if (m_grid.find(northCell) != m_grid.end())
					{
						if (m_grid[northCell].GetCellType() == EMPTY)
						{
							availableCells.push_back(northCell);
							availableCellsCon.push_back(northCellCon);
						}
						else if (m_grid[northCell].GetCellType() == ROOM)
						{
							foundRoomCells.push_back(northCell);
							foundRoomsCellsCon.push_back(northCellCon);
						}
					}
					if (m_grid.find(eastCell) != m_grid.end())
					{
						if (m_grid[eastCell].GetCellType() == EMPTY)
						{
							availableCells.push_back(eastCell);
							availableCellsCon.push_back(eastCellCon);
						}
						else if (m_grid[eastCell].GetCellType() == ROOM)
						{
							foundRoomCells.push_back(eastCell);
							foundRoomsCellsCon.push_back(eastCellCon);
						}
					}
					if (m_grid.find(southCell) != m_grid.end())
					{
						if (m_grid[southCell].GetCellType() == EMPTY)
						{
							availableCells.push_back(southCell);
							availableCellsCon.push_back(southCellCon);
						}
						else if (m_grid[southCell].GetCellType() == ROOM)
						{
							foundRoomCells.push_back(southCell);
							foundRoomsCellsCon.push_back(southCellCon);
						}
					}
					if (m_grid.find(westCell) != m_grid.end())
					{
						if (m_grid[westCell].GetCellType() == EMPTY)
						{
							availableCells.push_back(westCell);
							availableCellsCon.push_back(westCellCon);
						}
						else if (m_grid[westCell].GetCellType() == ROOM)
						{
							foundRoomCells.push_back(westCell);
							foundRoomsCellsCon.push_back(westCellCon);
						}
					}

					if (foundRoomCells.size () > 0)
					{
						bool found = false;
						// check if the found rooms cells is in the it->second room
						for (int a = 0; a != foundRoomCells.size(); a++)
						{
							it = std::find(m_roomsCells[m_connectingRooms[i].second].begin(), 
								m_roomsCells[m_connectingRooms[i].second].end(), 
								foundRoomCells[a]);
							if (it != m_roomsCells[m_connectingRooms[i].second].end())
							{
								if (m_grid[foundRoomsCellsCon[a]].GetCellType() != ROOM_CORNER && 
									m_grid[foundRoomsCellsCon[a]].GetCellType() != ROOM_EDGE)
								{
									// found room
									m_grid[startCell].SetCellType(PATH);
									m_grid[foundRoomsCellsCon[a]].SetCellType(PATH);

									startAndEndCells[startCell].push_back(foundRoomsCellsCon[a]);
									//m_grid[startCell].SetCellType(VERTICAL_DOOR);
									//m_doorCells.push_back(foundRoomsCellsCon[a]);
									//m_doorCells.push_back(startCell);

									m_doorCells.push_back(JoiningDoorCells());
									m_doorCells.back().position[0] = startCell;
									m_doorCells.back().position[1] = foundRoomsCellsCon[a];
									m_doorCells.back().room[0] = m_connectingRooms[i].first;
									m_doorCells.back().room[1] = m_connectingRooms[i].second;
									found = true;
									break;
								}
							}
						}

						if (found)
						{
							pathFound = true;
							break;
						}

						foundRoomCells.clear();
						foundRoomsCellsCon.clear();
					}

					if (availableCells.size() > 0)
					{
						// can find a cell to go to
						int nextCell = rand() % availableCells.size();
						
						currentCell = availableCells[nextCell];
						centreCell = availableCellsCon[nextCell];
						m_grid[centreCell].SetCellType(PATH);
						m_grid[currentCell].SetCellType(PATH);
						cellsWithPaths.push_back(currentCell);

						pathTaken.push(currentCell);
						pathTaken.push(centreCell);

						visitedCells.push(currentCell);
						visitedCellsCon.push(centreCell);
						availableCells.clear();
						availableCellsCon.clear();
					}
					else
					{
						// no path found so go back
						if (visitedCells.empty())
						{
							cellsWithPaths.erase(cellsWithPaths.end() - (int)(pathTaken.size() * 0.5f), cellsWithPaths.end());
											
								// check if pathTaken.top() is a surrounding room cell
								// if yes, then don't change paths to empty and empty pathTaken
							
							bool isRoomCell = false;
							//for (RoomsCells::iterator roomIt = m_surroundingRoomsCells.begin();
							//	roomIt != m_surroundingRoomsCells.end(); ++roomIt)
							//{
							//	std::vector<CellPosition>::iterator findRoomIt;
							//	findRoomIt = std::find(roomIt->second.begin(), roomIt->second.end(), startCell);
							//	if (findRoomIt != roomIt->second.end())
							//	{
							//		isRoomCell = true;
							//		break;
							//	}
							//}
							//if (!isRoomCell)
							//{
							while(!pathTaken.empty())
							{
								m_grid[pathTaken.top()].SetCellType(EMPTY);
								pathTaken.pop();
							}
							//}

							//for (int e = 0; e != startableCells.size(); e++)
							//{
							//	if (startableCells[e] == startCell)
							//	{
							//		startableCellsVisited[e] = false;
							//	}
							//}

							// check if the first and second rooms are next to each other
							//bool roomsAreTouching = false;
							//std::vector<CellPosition>::iterator roomCheckIt;
							//for (int w = 0; w != m_roomsCells[m_connectingRooms[i].first].size(); w++)
							//{
							//	CellPosition toCheckCell = m_roomsCells[m_connectingRooms[i].first][w];
							//	
							//	CellPosition north(toCheckCell.first, toCheckCell.second - 2);
							//	CellPosition east(toCheckCell.first + 2, toCheckCell.second);
							//	CellPosition south(toCheckCell.first, toCheckCell.second + 2);
							//	CellPosition west(toCheckCell.first - 2, toCheckCell.second);

							//	// north
							//	roomCheckIt = std::find(m_roomsCells[m_connectingRooms[i].second].begin(),
							//		m_roomsCells[m_connectingRooms[i].second].end(), north);
							//	if (roomCheckIt != m_roomsCells[m_connectingRooms[i].second].end())
							//	{
							//		// the rooms are next to each other
							//		roomsAreTouching = true;
							//		break;
							//	}

							//	// east								
							//	roomCheckIt = std::find(m_roomsCells[m_connectingRooms[i].second].begin(),
							//		m_roomsCells[m_connectingRooms[i].second].end(), east);
							//	if (roomCheckIt != m_roomsCells[m_connectingRooms[i].second].end())
							//	{
							//		// the rooms are next to each other
							//		roomsAreTouching = true;
							//		break;
							//	}

							//	// south								
							//	roomCheckIt = std::find(m_roomsCells[m_connectingRooms[i].second].begin(),
							//		m_roomsCells[m_connectingRooms[i].second].end(), south);
							//	if (roomCheckIt != m_roomsCells[m_connectingRooms[i].second].end())
							//	{
							//		// the rooms are next to each other
							//		roomsAreTouching = true;
							//		break;
							//	}

							//	// west								
							//	roomCheckIt = std::find(m_roomsCells[m_connectingRooms[i].second].begin(),
							//		m_roomsCells[m_connectingRooms[i].second].end(), west);
							//	if (roomCheckIt != m_roomsCells[m_connectingRooms[i].second].end())
							//	{
							//		// the rooms are next to each other
							//		roomsAreTouching = true;
							//		break;
							//	}
							//}

							//if (!roomsAreTouching)
							//{
								m_grid[startCell].SetCellType(EMPTY);
							//}
							

							//if (roomCheckIt != m_surroundingRoomsCells[m_connectingRooms[i].second].end())
							//{
							//	m_grid[startCell].SetCellType(EMPTY);
							//}

							pathFound = false;
							break;
						}
						
						//cellsWithPaths.erase(cellsWithPaths.end() - (int)(pathTaken.size() * 0.5f), cellsWithPaths.end());
						//while(!pathTaken.empty())
						//{
						//	//m_grid[pathTaken.top()].SetCellType(EMPTY);
						//	pathTaken.pop();
						//}

						currentCell = visitedCells.top();
						centreCell = visitedCellsCon.top();
						visitedCellsCon.pop();
						visitedCells.pop();
					}				
				}
			}
			
			if (failedToFindPath)
			{
				// search a path from room 2 to visited cells

				CellPosition startCell = currentCell;

				// 1: find % 2 cells
				std::map<int, CellPosition> startableCells;
				std::map<int, bool> startableCellsVisited;

				int startableCellsCounter = 0;
				for (int w = 0; w != m_surroundingRoomsCells[m_connectingRooms[i].second].size(); w++)
				{
					xMod2 = false;
					yMod2 = false;
					CellPosition tempCell = m_surroundingRoomsCells[m_connectingRooms[i].second][w];
					if (m_grid[tempCell].GetCellType() != EDGE && m_grid[tempCell].GetCellType() != ROOM &&
						m_grid[tempCell].GetCellType() != ROOM_CORNER && m_grid[tempCell].GetCellType() != PATH &&
						m_grid[tempCell].GetCellType() != ROOM_EDGE)
					{
						if (tempCell.first % 2 == 0)
						{
							xMod2 = true;
						}
						if (tempCell.second % 2 == 0)
						{
							yMod2 = true;
						}
					}

					if ((xMod2) && (yMod2))
					{
						startableCells[startableCellsCounter] = tempCell;
						startableCellsVisited[startableCellsCounter] = false;
						startableCellsCounter++;
					}
				}


				// 2: check all available % 2 cells to find an available start cell
				bool foundPath = false;
				while (!foundPath)
				{
					std::vector<int> startableCellsVisitable;
					for (int w = 0; w != startableCells.size(); w++)
					{
						if (startableCellsVisited[w] == false)
						{
							startableCellsVisitable.push_back(w);
						}
					}

					if (startableCellsVisitable.size() == 0)
					{
						// no more paths to go to

						//std::wstring wSeedNum = L"Failed to generate maze, seed: ";
						//wSeedNum += ToWString(m_seed);
						failedToFindPath = true;
						//DX11ErrorMsg(wSeedNum.c_str(), L"Maze::GeneratePathsDFS()", MB_OK);
						break;
					}
					else
					{
						int nextStart = rand() % startableCellsVisitable.size();
						currentCell = startableCells[startableCellsVisitable[nextStart]];
						startCell = currentCell;
						startableCellsVisited[startableCellsVisitable[nextStart]] = true;
					}

					CellPosition currentCentre = currentCell;

					std::stack<CellPosition> visitedCells;
					std::stack<CellPosition> visitedCellsCon;
					std::vector<CellPosition> availableCells;
					std::vector<CellPosition> availableCellsCon;

					std::vector<CellPosition> foundRoomCells;
					std::vector<CellPosition> foundRoomsCellsCon;

					std::vector<CellPosition> visitedPathCells;

					//m_grid[currentCell].SetCellType(PATH);
					visitedCells.push(currentCell);
					visitedCellsCon.push(currentCell);
					//cellsWithPaths.push_back(currentCell);
					
					std::vector<CellPosition>::iterator it;
					while (true)
					{
						it = std::find(cellsWithPaths.begin(), cellsWithPaths.end(), currentCell);
						if (it != cellsWithPaths.end())
						{
							//if (m_grid[currentCell].GetCellType() != ROOM_CORNER)
							//{
								//m_grid[*it].SetCellType(VERTICAL_DOOR);
								//m_grid[startCell].SetCellType(VERTICAL_DOOR);

								//m_doorCells.push_back(*it);
								//m_doorCells.push_back(startCell);
							
								m_grid[startCell].SetCellType(PATH);
								m_doorCells.push_back(JoiningDoorCells());
								startAndEndCells[startCell].push_back(*it);
								m_doorCells.back().position[0] = *it;
								m_doorCells.back().position[1] = startCell;
								m_doorCells.back().room[0] = m_connectingRooms[i].first;
								m_doorCells.back().room[1] = m_connectingRooms[i].second;

								foundPath = true;
								break;
							//}
						}
						
						CellPosition northCell = CellPosition(currentCell.first, currentCell.second - 2);
						CellPosition eastCell = CellPosition(currentCell.first + 2, currentCell.second);
						CellPosition southCell = CellPosition(currentCell.first, currentCell.second + 2);
						CellPosition westCell = CellPosition(currentCell.first - 2, currentCell.second);

						// northCellCon (Con = connecting)
						CellPosition northCellCon = CellPosition(currentCell.first, currentCell.second - 1);
						CellPosition eastCellCon = CellPosition(currentCell.first + 1, currentCell.second);
						CellPosition southCellCon = CellPosition(currentCell.first, currentCell.second + 1);
						CellPosition westCellCon = CellPosition(currentCell.first - 1, currentCell.second);

						if (m_grid.find(northCell) != m_grid.end())
						{
							it = std::find(visitedPathCells.begin(), visitedPathCells.end(), northCell);
							if (it == visitedPathCells.end())
							{
								if (m_grid[northCell].GetCellType() == EMPTY ||
									m_grid[northCell].GetCellType() == PATH)
								{
									availableCells.push_back(northCell);
									availableCellsCon.push_back(northCellCon);
								}
							}
						}
						if (m_grid.find(eastCell) != m_grid.end())
						{
							it = std::find(visitedPathCells.begin(), visitedPathCells.end(), eastCell);
							if (it == visitedPathCells.end())
							{
								if (m_grid[eastCell].GetCellType() == EMPTY ||
									m_grid[eastCell].GetCellType() == PATH)
								{
									availableCells.push_back(eastCell);
									availableCellsCon.push_back(eastCellCon);
								}
							}
						}
						if (m_grid.find(southCell) != m_grid.end())
						{
							it = std::find(visitedPathCells.begin(), visitedPathCells.end(), southCell);
							if (it == visitedPathCells.end())
							{
								if (m_grid[southCell].GetCellType() == EMPTY ||
									m_grid[southCell].GetCellType() == PATH)
								{
									availableCells.push_back(southCell);
									availableCellsCon.push_back(southCellCon);
								}
							}
						}
						if (m_grid.find(westCell) != m_grid.end())
						{
							it = std::find(visitedPathCells.begin(), visitedPathCells.end(), westCell);
							if (it == visitedPathCells.end())
							{
								if (m_grid[westCell].GetCellType() == EMPTY ||
									m_grid[westCell].GetCellType() == PATH)
								{
									availableCells.push_back(westCell);
									availableCellsCon.push_back(westCellCon);
								}
							}
						}

						if (availableCells.size() > 0)
						{
							int nextCell = rand() % availableCells.size();
							currentCell = availableCells[nextCell];
							currentCentre = availableCellsCon[nextCell];

							visitedPathCells.push_back(currentCell);
							visitedCells.push(currentCell);
							visitedCellsCon.push(currentCentre);
							m_grid[currentCentre].SetCellType(PATH);
							m_grid[currentCell].SetCellType(PATH);

							pathTaken.push(currentCell);
							pathTaken.push(currentCentre);

							availableCells.clear();
							availableCellsCon.clear();
						}
						else
						{
							if (visitedCells.empty())
							{
								// check for failed cell doors
								//for (int e = 0; e != startableCells.size(); e++)
								//{
								//	CellPosition
								//}

								std::wstring wSeedNum = L"Failed to generate maze, seed: ";
								wSeedNum += ToWString(m_seed);
								DX11ErrorMsg(wSeedNum.c_str(), L"Maze::GeneratePathsDFS()", MB_OK);
								break;
							}

							currentCell = visitedCells.top();
							visitedCells.pop();
							visitedCellsCon.pop();
						}
					}
				}
				// find room 2 available path: end
			}		

			// set paths in m_grid
			//while(!pathTaken.empty())
			//{

			//}
		}
		// generate path: end
	}

	for (std::map<CellPosition, std::vector<CellPosition>>::iterator it = startAndEndCells.begin();
		it != startAndEndCells.end(); ++it)
	{
		m_grid[it->first].SetCellType(PATH);
		for (int i = 0; i != it->second.size(); i++)
		{
			m_grid[it->second[i]].SetCellType(PATH);
		}
	}

	cellsWithPaths.clear();
	return;
}

void Maze::CalculateDoorCells()
{
	for (int i = 0; i != m_doorCells.size(); i++)
	{
		bool foundRoom1 = false;
		bool foundRoom2 = false;

		CellPosition start = m_doorCells[i].position[0];
		CellPosition end = m_doorCells[i].position[1];

		int startRoom = m_doorCells[i].room[0];
		int endRoom = m_doorCells[i].room[1];

		std::vector<CellPosition>::iterator it;

		CellPosition north;
		CellPosition east;
		CellPosition south;
		CellPosition west;
		
		// check north/east/south/west cells of start cell
		// if one or more is a room then check if the room cell is the same as the start room
		
		north = CellPosition(start.first, start.second + 1);
		east = CellPosition(start.first - 1, start.second);
		south = CellPosition(start.first, start.second - 1);
		west = CellPosition(start.first + 1, start.second);

		if (m_grid[north].GetCellType() == ROOM_EDGE && !foundRoom1)
		{
			it = std::find(m_roomsCells[startRoom].begin(), m_roomsCells[startRoom].end(), north);
			if (it != m_roomsCells[startRoom].end())
			{
				m_grid[north].SetCellType(VERTICAL_DOOR);
				foundRoom1 = true;
			}
		}
		if (m_grid[east].GetCellType() == ROOM_EDGE && !foundRoom1)
		{
			it = std::find(m_roomsCells[startRoom].begin(), m_roomsCells[startRoom].end(), east);
			if (it != m_roomsCells[startRoom].end())
			{
				m_grid[east].SetCellType(HORIZONTAL_DOOR);
				foundRoom1 = true;
			}
		}
		if (m_grid[south].GetCellType() == ROOM_EDGE && !foundRoom1)
		{
			it = std::find(m_roomsCells[startRoom].begin(), m_roomsCells[startRoom].end(), south);
			if (it != m_roomsCells[startRoom].end())
			{
				m_grid[south].SetCellType(VERTICAL_DOOR);
				foundRoom1 = true;
			}
		}
		if (m_grid[west].GetCellType() == ROOM_EDGE && !foundRoom1)
		{
			it = std::find(m_roomsCells[startRoom].begin(), m_roomsCells[startRoom].end(), west);
			if (it != m_roomsCells[startRoom].end())
			{
				m_grid[west].SetCellType(HORIZONTAL_DOOR);
				foundRoom1 = true;
			}
		}
		

		north = CellPosition(end.first, end.second + 1);
		east = CellPosition(end.first - 1, end.second);
		south = CellPosition(end.first, end.second - 1);
		west = CellPosition(end.first + 1, end.second);

		if (m_grid[north].GetCellType() == ROOM_EDGE && !foundRoom2)
		{
			it = std::find(m_roomsCells[endRoom].begin(), m_roomsCells[endRoom].end(), north);
			if (it != m_roomsCells[endRoom].end())
			{
				m_grid[north].SetCellType(VERTICAL_DOOR);
				foundRoom2 = true;
			}
		}
		if (m_grid[east].GetCellType() == ROOM_EDGE && !foundRoom2)
		{
			it = std::find(m_roomsCells[endRoom].begin(), m_roomsCells[endRoom].end(), east);
			if (it != m_roomsCells[endRoom].end())
			{
				m_grid[east].SetCellType(HORIZONTAL_DOOR);
				foundRoom2 = true;
			}
		}
		if (m_grid[south].GetCellType() == ROOM_EDGE && !foundRoom2)
		{
			it = std::find(m_roomsCells[endRoom].begin(), m_roomsCells[endRoom].end(), south);
			if (it != m_roomsCells[endRoom].end())
			{
				m_grid[south].SetCellType(VERTICAL_DOOR);
				foundRoom2 = true;
			}
		}
		if (m_grid[west].GetCellType() == ROOM_EDGE && !foundRoom2)
		{
			it = std::find(m_roomsCells[endRoom].begin(), m_roomsCells[endRoom].end(), west);
			if (it != m_roomsCells[endRoom].end())
			{
				m_grid[west].SetCellType(HORIZONTAL_DOOR);
				foundRoom2 = true;
			}
		}
	}

	for (Grid::iterator it = m_grid.begin(); it != m_grid.end(); ++it)
	{
		if (it->second.GetCellType() == VERTICAL_DOOR || it->second.GetCellType() == HORIZONTAL_DOOR)
		{
			m_doorsForDrawing.push_back(it->first);
		}
	}
	return;
}

void Maze::CalculateWallCells()
{
	// go through all cells
	// check the north/east/south/west cells,
	// if they are empty then mark it as a wall

	for (Grid::iterator it = m_grid.begin(); it != m_grid.end(); ++it)
	{
		CellPosition curCell = it->first;
		
		if (it->second.GetCellType() != EMPTY && it->second.GetCellType() != EDGE &&
			it->second.GetCellType() != WALL)
		{
			CellPosition north(curCell.first, curCell.second - 1);
			CellPosition east(curCell.first + 1, curCell.second);
			CellPosition south(curCell.first, curCell.second + 1);
			CellPosition west(curCell.first - 1, curCell.second);

			Grid::iterator findIt;
		
			findIt = m_grid.find(north);
			if (findIt != m_grid.end())
			{
				if (m_grid[north].GetCellType() == EMPTY || m_grid[north].GetCellType() == EDGE)
				{
					m_grid[north].SetCellType(WALL);
				}
			}
		
			findIt = m_grid.find(east);
			if (findIt != m_grid.end())
			{
				if (m_grid[east].GetCellType() == EMPTY || m_grid[east].GetCellType() == EDGE)
				{
					m_grid[east].SetCellType(WALL);
				}
			}
				
			findIt = m_grid.find(south);
			if (findIt != m_grid.end())
			{
				if (m_grid[south].GetCellType() == EMPTY || m_grid[south].GetCellType() == EDGE)
				{
					m_grid[south].SetCellType(WALL);
				}
			}
			
			findIt = m_grid.find(west);
			if (findIt != m_grid.end())
			{
				if (m_grid[west].GetCellType() == EMPTY || m_grid[west].GetCellType() == EDGE)
				{
					m_grid[west].SetCellType(WALL);
				}
			}
		}
	}
}

void Maze::CalculateRoomEdges()
{
	// calculate top left and bot right cells of room
	for (int i = 0; i != m_roomsCells.size(); i++)
	{
		CellPosition topLeft(65535, 65535);
		CellPosition botRight(-1, -1);
		
		for (int j = 0; j != m_roomsCells[i].size(); j++)
		{
			CellPosition curCell = m_roomsCells[i][j];

			if (topLeft.first > curCell.first)
			{
				topLeft.first = curCell.first;
			}
			if (topLeft.second > curCell.second)
			{
				topLeft.second = curCell.second;
			}
			if (botRight.first < curCell.first)
			{
				botRight.first = curCell.first;
			}
			if (botRight.second < curCell.second)
			{
				botRight.second = curCell.second;
			}
		}

		for (int x = 0; x != m_sizeOfRooms[i].first; x++)
		{
			CellPosition top = topLeft;
			CellPosition bot = botRight;
			top.first = topLeft.first + x;
			bot.first = botRight.first - x;

			if (m_grid[top].GetCellType() != VERTICAL_DOOR && m_grid[top].GetCellType() != HORIZONTAL_DOOR &&
				m_grid[top].GetCellType() != ROOM_CORNER)
			{
				m_grid[top].SetCellType(ROOM_EDGE);
			}
			if (m_grid[bot].GetCellType() != VERTICAL_DOOR && m_grid[bot].GetCellType() != HORIZONTAL_DOOR &&
				m_grid[bot].GetCellType() != ROOM_CORNER)
			{
				m_grid[bot].SetCellType(ROOM_EDGE);
			}
		}
		for (int y = 0; y != m_sizeOfRooms[i].second; y++)
		{
			CellPosition left = topLeft;
			CellPosition right = botRight;
			left.second = topLeft.second + y;
			right.second = botRight.second - y;
			
			if (m_grid[left].GetCellType() != VERTICAL_DOOR && m_grid[left].GetCellType() != HORIZONTAL_DOOR &&
				m_grid[left].GetCellType() != ROOM_CORNER)
			{
				m_grid[left].SetCellType(ROOM_EDGE);
			}
			if (m_grid[right].GetCellType() != VERTICAL_DOOR && m_grid[right].GetCellType() != HORIZONTAL_DOOR &&
				m_grid[right].GetCellType() != ROOM_CORNER)
			{
				m_grid[right].SetCellType(ROOM_EDGE);
			}
		}
	}
}

void Maze::CalculateToDrawPaths()
{
	for (Grid::iterator it = m_grid.begin(); it != m_grid.end(); ++it)
	{
		CellType curCellType = it->second.GetCellType();
		if (curCellType == PATH || curCellType == VERTICAL_DOOR || curCellType == HORIZONTAL_DOOR)
		{
			m_toDrawPaths.push_back(it->first);
		}
	}

	for (int i = 0; i != m_roomCells.size(); i++)
	{
		m_toDrawPaths.insert(m_toDrawPaths.end(), m_roomsCells[i].begin(), m_roomsCells[i].end());
	}
}

void Maze::CalculateToDrawWalls()
{
	for (Grid::iterator it = m_grid.begin(); it != m_grid.end(); ++it)
	{
		CellType curCellType = it->second.GetCellType();
		if (curCellType == WALL || curCellType == CORNER || curCellType == ROOM_EDGE ||
			curCellType == ROOM_CORNER)
		{
			m_toDrawWalls.push_back(it->first);
		}
	}
}

Edges Maze::GetEdgeList(const CellPosition& cell)
{
	CellPosition north(cell.first, cell.second - 1);
	CellPosition east(cell.first + 1, cell.second);
	CellPosition south(cell.first, cell.second + 1);
	CellPosition west(cell.first - 1, cell.second);

	Edges e;

	// check if n/e/s/w cell is in m_grid
	Grid::iterator it;
	it = m_grid.find(north);
	if (it != m_grid.end())
	{
		if (m_grid[it->first].GetCellType() == PATH || 
			m_grid[it->first].GetCellType() == ROOM ||
			m_grid[it->first].GetCellType() == VERTICAL_DOOR || 
			m_grid[it->first].GetCellType() == HORIZONTAL_DOOR)
		{
			GraphEdge ge(cell, it->first, 1.0f);
			e.push_back(ge);
		}
	}

	it = m_grid.find(east);
	if (it != m_grid.end())
	{
		if (m_grid[it->first].GetCellType() == PATH || 
			m_grid[it->first].GetCellType() == ROOM ||
			m_grid[it->first].GetCellType() == VERTICAL_DOOR || 
			m_grid[it->first].GetCellType() == HORIZONTAL_DOOR)
		{
			GraphEdge ge(cell, it->first, 1.0f);
			e.push_back(ge);
		}
	}

	it = m_grid.find(south);
	if (it != m_grid.end())
	{
		if (m_grid[it->first].GetCellType() == PATH || 
			m_grid[it->first].GetCellType() == ROOM ||
			m_grid[it->first].GetCellType() == VERTICAL_DOOR || 
			m_grid[it->first].GetCellType() == HORIZONTAL_DOOR)
		{
			GraphEdge ge(cell, it->first, 1.0f);
			e.push_back(ge);
		}
	}

	it = m_grid.find(west);
	if (it != m_grid.end())
	{
		if (m_grid[it->first].GetCellType() == PATH || 
			m_grid[it->first].GetCellType() == ROOM ||
			m_grid[it->first].GetCellType() == VERTICAL_DOOR || 
			m_grid[it->first].GetCellType() == HORIZONTAL_DOOR)
		{
			GraphEdge ge(cell, it->first, 1.0f);
			e.push_back(ge);
		}
	}

	return e;
}

float Maze::CalculateHeuristic(const CellPosition& start, const CellPosition& end)
{	
	CellPosition heuristic;
	heuristic.first = start.first - end.first;
	heuristic.second = start.second - end.second;
	// make positive heuristic values
	if (heuristic.first < 0)
	{
		heuristic.first *= -1;
	}
	if (heuristic.second < 0)
	{
		heuristic.second *= -1;
	}

	float cost = (float)(heuristic.first + heuristic.second);

	return cost;
}

void Maze::CalculateAStar(const CellPosition& cp)
{
	m_trail.clear();

	CellPosition startCell = m_currentCell;
	CellPosition endCell = cp;
	CellPosition heuristic;
	heuristic.first = startCell.first - endCell.first;
	heuristic.second = startCell.second - endCell.second;
	// make positive heuristic values
	if (heuristic.first < 0)
	{
		heuristic.first *= -1;
	}
	if (heuristic.second < 0)
	{
		heuristic.second *= -1;
	}

	Costs fCosts;
	Costs gCosts;
	//std::set<CellPosition> finalPath;

	NodePriorityQueue nodes(&fCosts);
	std::set<CellPosition> visited;
	std::queue<CellPosition> path;
	//std::vector<CellPosition> surroundingCells;
	
	typedef std::pair<CellPosition, CellPosition> ConnectingCell;
	typedef std::vector<ConnectingCell> ConnectingCells;
	ConnectingCells conCells;

	// getedgelist = get surrounding path of current cell
	
	// set g-cost for getting to start node to zero
	Edges e = GetEdgeList(startCell);
	Edges connectingEdges;
	
	for (int i = 0; i != e.size(); i++)
	{
		gCosts[e[i].GetEndId()] = 0;
	}
	e.clear();
	// push start node onto priority queue
	nodes.Push(startCell);
	path.push(nodes.Top());
	while(!nodes.IsEmpty())
	{
		// get front node from priority queue and pop it
		CellPosition curNode = nodes.Top();
		//path.push(curNode);
		nodes.Pop();
		// add node to visited set
		visited.insert(curNode);

		// is nodes.top == end?
		if (curNode == endCell)
		{
			m_trail.clear();
			m_trail.insert(endCell);
			CellPosition start = endCell;
			CellPosition curCell = start;

			while (curCell != startCell)
			{
				ConnectingCells::iterator conCellIt;

				for (int j = 0; j != conCells.size(); j++)
				{
					if (conCells[j].first == curCell)
					{
						curCell = conCells[j].second;
					}
				}
				m_trail.insert(curCell);
			}

			return;
		}

		// if not then get list of edges connected to current node
		Edges edges = GetEdgeList(curNode);
		CellPosition lastInserted(-1, -1);

		// for each of the nodes
		for (int i = 0; i != edges.size(); i++)
		{
			// calc the g-cost and reaching the destination node
			float cost = gCosts[curNode] + edges[i].GetCost();


			// if destination node is not already visited
			if (visited.find(edges[i].GetEndId()) == visited.end())
			{
				// then set the g-cost and f-cost to getting to this node
				gCosts[edges[i].GetEndId()] = cost;
				fCosts[edges[i].GetEndId()] = cost + CalculateHeuristic(edges[i].GetStartId(), edges[i].GetEndId());
				// push the new node to the back of the queue
				nodes.Push(edges[i].GetEndId());

				// mark node as visited
				visited.insert(edges[i].GetEndId());

				conCells.push_back(ConnectingCell(edges[i].GetEndId(), edges[i].GetStartId()));
			}
			// else if the new g-cost is less than the stored g-cost
			else if (gCosts[edges[i].GetEndId()] > cost)
			{
				//path.push(edges[i].GetStartId());
				// then update the g + fcosts
				gCosts[edges[i].GetEndId()] = cost;
				float heuristicCost = CalculateHeuristic(edges[i].GetStartId(), edges[i].GetEndId());
				fCosts[edges[i].GetEndId()] = cost + heuristicCost;
				
			}
		}
		nodes.ReSort();
	}

	return;
}

void Maze::DrawSouthWall(const D3DXVECTOR3& pos)
{
	TheObjMeshManager::Instance()->Translate("SouthWall", m_position);
	TheObjMeshManager::Instance()->Translate("SouthWall", pos);
	TheObjMeshManager::Instance()->Scale("SouthWall", m_cellSize.x * 0.5f, 1, 1);

	TheObjMeshManager::Instance()->Draw("SouthWall");
}

void Maze::DrawWestWall(const D3DXVECTOR3& pos)
{
	TheObjMeshManager::Instance()->Translate("WestWall", m_position);
	TheObjMeshManager::Instance()->Translate("WestWall", pos);
	TheObjMeshManager::Instance()->Scale("WestWall", 1, 1, m_cellSize.z * 0.5f);

	TheObjMeshManager::Instance()->Draw("WestWall");
}

void Maze::DrawSouthDoor(const D3DXVECTOR3& pos)
{
	TheObjMeshManager::Instance()->Translate("SouthDoor", m_position);
	TheObjMeshManager::Instance()->Translate("SouthDoor", pos);
	TheObjMeshManager::Instance()->Scale("SouthDoor", m_cellSize.x * 0.5f, 1, 1);

	TheObjMeshManager::Instance()->Draw("SouthDoor");
}

void Maze::DrawWestDoor(const D3DXVECTOR3& pos)
{
	TheObjMeshManager::Instance()->Translate("WestDoor", m_position);
	TheObjMeshManager::Instance()->Translate("WestDoor", pos);
	TheObjMeshManager::Instance()->Scale("WestDoor", 1, 1, m_cellSize.z * 0.5f);

	TheObjMeshManager::Instance()->Draw("WestDoor");
}

void Maze::DrawVerticalWall(const D3DXVECTOR3& pos)
{
	TheObjMeshManager::Instance()->SetColour("crate_textured", D3DXVECTOR4(0.0f, 0.0f, 0.0f, 1.0f));
	TheObjMeshManager::Instance()->Translate("crate_textured", m_position);
	TheObjMeshManager::Instance()->Translate("crate_textured", pos);
	TheObjMeshManager::Instance()->Scale("crate_textured", m_cellSize.x, 10, m_cellSize.y);

	TheObjMeshManager::Instance()->Draw("crate_textured");
}
void Maze::DrawHorizontalWall(const D3DXVECTOR3& pos)
{
	TheObjMeshManager::Instance()->SetColour("crate_textured", D3DXVECTOR4(0.0f, 0.0f, 0.0f, 1.0f));
	TheObjMeshManager::Instance()->Translate("crate_textured", m_position);
	TheObjMeshManager::Instance()->Translate("crate_textured", pos);
	TheObjMeshManager::Instance()->Scale("crate_textured", m_cellSize.x, 10, m_cellSize.y);

	TheObjMeshManager::Instance()->Draw("crate_textured");
}
void Maze::DrawVerticalDoor(const D3DXVECTOR3& pos)
{
	TheObjMeshManager::Instance()->Translate("SouthDoor", m_position);
	TheObjMeshManager::Instance()->Translate("SouthDoor", pos);
	TheObjMeshManager::Instance()->Scale("SouthDoor", m_cellSize.x * 0.5f, 1, 1);

	TheObjMeshManager::Instance()->Draw("SouthDoor");
}

void Maze::DrawHorizontalDoor(const D3DXVECTOR3& pos)
{
	TheObjMeshManager::Instance()->Translate("WestDoor", m_position);
	TheObjMeshManager::Instance()->Translate("WestDoor", pos);
	TheObjMeshManager::Instance()->Scale("WestDoor", 1, 1, m_cellSize.z * 0.5f);

	TheObjMeshManager::Instance()->Draw("WestDoor");
}

void Maze::DrawCell(const CellPosition& cell)
{
	TheObjMeshManager::Instance()->SetColour("maze_floor", D3DXVECTOR4(0.0f, 0.0f, 0.0f, 1.0f));
	TheObjMeshManager::Instance()->Translate("maze_floor", m_position);
	D3DXVECTOR3 curCell3dPos = m_grid[cell].GetPos();
	curCell3dPos.y += m_cellSize.y * 0.5f;
	TheObjMeshManager::Instance()->Translate("maze_floor", curCell3dPos);
	TheObjMeshManager::Instance()->Scale("maze_floor", m_cellSize);
	TheObjMeshManager::Instance()->Draw("maze_floor");
}

void Maze::DrawWall(const CellPosition& cell)
{
	// go through path/room cells and check if the north/east/south/west cells are in m_wallCells
	TheObjMeshManager::Instance()->SetColour("crate_textured", D3DXVECTOR4(0.0f, 0.5f, 0.5f, 1.0f));
	TheObjMeshManager::Instance()->Translate("crate_textured", m_position);
	D3DXVECTOR3 curCell3dPos = m_grid[cell].GetPos();
	curCell3dPos.y += m_cellSize.y;
	TheObjMeshManager::Instance()->Translate("crate_textured", curCell3dPos);
	TheObjMeshManager::Instance()->Scale("crate_textured", m_cellSize);
	TheObjMeshManager::Instance()->Draw("crate_textured");
}

void Maze::Draw()
{	
	//CalculateCurrentCell();

	////static Text test;
	////test.Translate(D3DXVECTOR3(0.0f, 0.0f, 0.0f));
	////test.Update("picked: " + ToString(m_pickedColour));
	////test.Draw();

	//static std::vector<D3DXVECTOR4> colours;


	std::map<D3DXVECTOR4, CellPosition>::iterator it5 = m_cellColours.find(m_pickedColour);
	static CellPosition m_pickedCell;

	if (it5 != m_cellColours.end())
	{
		m_pickedCell = m_cellColours[m_pickedColour];
		//if (m_grid[m_currentCell].GetCellType() == ROOM || 
		//	m_grid[m_currentCell].GetCellType() == VERTICAL_DOOR ||
		//	m_grid[m_currentCell].GetCellType() == HORIZONTAL_DOOR ||
		//	m_grid[m_currentCell].GetCellType() == PATH)
		//{
		//	CalculateAStar(m_pickedCell);
		//}

		//m_cellColours.find(m_pickedCell);
	}
	
	// mini mapped picked colour
	D3DXVECTOR4 pickedColour = TheMiniMap::Instance()->GetPickedColour();
	std::map<D3DXVECTOR4, CellPosition>::iterator colit2 = m_cellColours.find(pickedColour);

	if (pickedColour.x != -1.0f)
	{
		for (std::map<D3DXVECTOR4, CellPosition>::iterator colIt = m_cellColours.begin();
			colIt != m_cellColours.end(); ++colIt)
		{
			if (pickedColour.x == colIt->first.x)
			{
				if (pickedColour.y == colIt->first.y)
				{
					if (pickedColour.z == colIt->first.z)
					{
						if (m_grid[m_currentCell].GetCellType() == ROOM || 
							m_grid[m_currentCell].GetCellType() == VERTICAL_DOOR ||
							m_grid[m_currentCell].GetCellType() == HORIZONTAL_DOOR ||
							m_grid[m_currentCell].GetCellType() == PATH)
						{
							CalculateAStar(colIt->second);
						}

						//Grid::iterator gridIt = m_grid.find(m_currentCell);
						//if (gridIt != m_grid.end())
						//{
						//	if (m_grid[m_currentCell].GetCellType() != EMPTY &&
						//		m_grid[m_currentCell].GetCellType() != EDGE &&
						//		m_grid[m_currentCell].GetCellType() != ROOM_EDGE)
						//	{
						//		CalculateAStar(colIt->second);
						//	}
						//}
						
#ifdef _DEBUG
						TheObjMeshManager::Instance()->SetColour("crate_textured", D3DXVECTOR4(1.0f, 1.0f, 1.0f, 1.0f));
						TheObjMeshManager::Instance()->Translate("crate_textured", m_position);
						D3DXVECTOR3 curCell3dPos = m_grid[colIt->second].GetPos();
						curCell3dPos.y += 5.0f;
						TheObjMeshManager::Instance()->Translate("crate_textured", curCell3dPos);
						TheObjMeshManager::Instance()->Scale("crate_textured", m_cellSize);
						TheObjMeshManager::Instance()->Draw("crate_textured");

						static Text t;
						t.Update("PickedCell: (" + ToString(colIt->second.first) + ", " + 
							ToString(colIt->second.second) + ")");
						t.Translate(D3DXVECTOR3(0.0f, 0.0f, 0.0f));
						t.Draw();
						// col
						t.Update("Col.R: " + ToString(colIt->first.x));
						t.Translate(D3DXVECTOR3(0.0f, 0.1f, 0.0f));
						t.Draw();
						t.Update("Col.G: " + ToString(colIt->first.y));
						t.Translate(D3DXVECTOR3(0.0f, 0.2f, 0.0f));
						t.Draw();
						t.Update("Col.B: " + ToString(colIt->first.z));
						t.Translate(D3DXVECTOR3(0.0f, 0.3f, 0.0f));
						t.Draw();
#endif
						break;
					}
				}
			}
		}
	}

	std::set<CellPosition>::iterator trailIt;
	for (trailIt = m_trail.begin(); trailIt != m_trail.end(); ++trailIt)
	{
		TheObjMeshManager::Instance()->SetColour("crate_textured", D3DXVECTOR4(0.0f, 1.0f, 0.0f, 1.0f));
		TheObjMeshManager::Instance()->Translate("crate_textured", m_position);
		D3DXVECTOR3 curCell3dPos = m_grid[*trailIt].GetPos();
		curCell3dPos.y += 5.0f;
		TheObjMeshManager::Instance()->Translate("crate_textured", curCell3dPos);
		TheObjMeshManager::Instance()->Scale("crate_textured", m_cellSize * 0.1f);
		TheObjMeshManager::Instance()->Draw("crate_textured");
	}

	TheObjMeshManager::Instance()->ChangeTexture("maze_floor", 
		TheDX11TextureManager::Instance()->UseTexture(L"../../Assets/floor_texture.png"));
	//TheObjMeshManager::Instance()->ChangeShader("maze_floor", "DefaultTexture");

	TheObjMeshManager::Instance()->ChangeTexture("crate_textured",
		TheDX11TextureManager::Instance()->UseTexture(L"../../Assets/wall_texture_small.png"));
	TheObjMeshManager::Instance()->ChangeShader("crate_textured", "DefaultTexture");

	//for (int i = 0; i != m_roomsCells.size(); i++)
	//{
	//	for (int j = 0; j != m_roomsCells[i].size(); j++)
	//	{
	//		CellPosition curPos = m_roomsCells[i][j];
	//		if (m_grid[curPos].GetCellType() == ROOM)
	//		{
	//			TheObjMeshManager::Instance()->SetColour("maze_floor", m_roomColours[i]);
	//			TheObjMeshManager::Instance()->Translate("maze_floor", m_position);
	//			D3DXVECTOR3 curCell3dPos = m_grid[curPos].GetPos();
	//			curCell3dPos.y += m_cellSize.y * 0.5f;
	//			TheObjMeshManager::Instance()->Translate("maze_floor", curCell3dPos);
	//			TheObjMeshManager::Instance()->Scale("maze_floor", m_cellSize);
	//			TheObjMeshManager::Instance()->Draw("maze_floor");
	//		}
	//		else if (m_grid[curPos].GetCellType() == ROOM_EDGE || m_grid[curPos].GetCellType() == ROOM_CORNER)
	//		{
	//			TheObjMeshManager::Instance()->SetColour("crate_textured", D3DXVECTOR4(m_roomColours[i].x - 0.5f, m_roomColours[i].y - 0.5f, m_roomColours[i].z - 0.5f, 1.0f));
	//			TheObjMeshManager::Instance()->Translate("crate_textured", m_position);
	//			D3DXVECTOR3 curCell3dPos = m_grid[curPos].GetPos();
	//			curCell3dPos.y += m_cellSize.y;
	//			TheObjMeshManager::Instance()->Translate("crate_textured", curCell3dPos);
	//			TheObjMeshManager::Instance()->Scale("crate_textured", m_cellSize);
	//			TheObjMeshManager::Instance()->Draw("crate_textured");
	//		}
	//	}
	//}
	//
	//CalculateCellsInVisibleRange();
	int num = m_toDrawWalls.size();
	for (int i = 0; i != num; i++)
	{
		//TheObjMeshManager::Instance()->SetColour("maze_floor", m_roomColours[i]);
		TheObjMeshManager::Instance()->Translate("crate_textured", m_position);
		D3DXVECTOR3 curCell3dPos = m_grid[m_toDrawWalls[i]].GetPos();
		curCell3dPos.y += m_cellSize.y;
		TheObjMeshManager::Instance()->Translate("crate_textured", curCell3dPos);
		TheObjMeshManager::Instance()->Scale("crate_textured", m_cellSize);
		TheObjMeshManager::Instance()->Draw("crate_textured");
	}

	TheObjMeshManager::Instance()->ChangeShader("maze_floor", "maze_floor_1");
	D3DXVECTOR3 size(m_gridSize.x * m_cellSize.x, 1.0f, m_gridSize.y * m_cellSize.z);

	TheObjMeshManager::Instance()->Translate("maze_floor", D3DXVECTOR3(0.0f, m_cellSize.y, 0.0f));
	TheObjMeshManager::Instance()->Scale("maze_floor", size * 2.0f);
	TheObjMeshManager::Instance()->Draw("maze_floor");

	TheObjMeshManager::Instance()->ChangeShader("maze_floor", "maze_floor_1");
	TheObjMeshManager::Instance()->ChangeShader("crate_textured", "crate_textured_1");


	// agent tests
	//static Agent a1;
	//static Agent a2;
	//static Agent a3;
	//static AgentGroup agentGroup;
	//static bool init = false;
	//if (!init)
	//{
	//	D3DXVECTOR3 pos = m_grid[m_roomsCells[0][14]].GetPos();
	//	//pos.x -= m_cellSize.x * (m_gridSize.x * 0.5f) + m_cellSize.x;
	//	//pos.z -= m_cellSize.z * (m_gridSize.y * 0.5f) + m_cellSize.z; 
	//	pos.y = 15.0f;

	//	a1.SetPosition(pos);

	//	pos = m_grid[m_roomsCells[0][21]].GetPos();
	//	//pos.x -= m_cellSize.x * (m_gridSize.x * 0.5f) + m_cellSize.x;
	//	//pos.z -= m_cellSize.z * (m_gridSize.y * 0.5f) + m_cellSize.z;
	//	pos.y = 15.0f;

	//	a2.SetPosition(pos);

	//	pos = m_grid[m_roomsCells[0][26]].GetPos();
	//	pos.x -= m_cellSize.x * (m_gridSize.x * 0.5f) + m_cellSize.x;
	//	pos.z -= m_cellSize.z * (m_gridSize.y * 0.5f) + m_cellSize.z; 
	//	pos.y = 15.0f;

	//	//a3.SetPosition(pos);
	//
	//	a1.SetMaxForce(10.0f);
	//	a2.SetMaxForce(5.0f);
	//	a3.SetMaxForce(0.5f);

	//	a1.SetMaxVel(D3DXVECTOR3(3.0f, 3.0f, 3.0f));
	//	a2.SetMaxVel(D3DXVECTOR3(1.0f, 1.0f, 1.0f));

	//	a1.SetTarget(&a3);
	//	a2.SetTarget(&a3);
	//	a3.SetTarget(&a2);

	//	a1.SetMass(0.8f);
	//	a2.SetMass(3.0f);
	//	a3.SetMass(5.0f);
	//	
	//	a1.SetColour(D3DXVECTOR4(0.5f, 0.0f, 0.0f, 1.0f));
	//	a2.SetColour(D3DXVECTOR4(0.0f, 0.5f, 0.0f, 1.0f));

	//	agentGroup.AddAgent(&a1);
	//	agentGroup.AddAgent(&a2);

	//	a1.SetGroup(&agentGroup);
	//	a2.SetGroup(&agentGroup);

	//	init = true;
	//}

	//D3DXVECTOR3 camPos = TheCameraManager::Instance()->GetCameraPos();
	//
	//camPos.x += m_cellSize.x * (m_gridSize.x * 0.5f);
	//camPos.z += m_cellSize.z * (m_gridSize.y * 0.5f);

	//a3.SetPosition(camPos);
	//
	////TheObjMeshManager::Instance()->SetColour("crate_textured", D3DXVECTOR4(1.0f, 1.0f, 1.0f, 0.5f));
	////TheObjMeshManager::Instance()->Translate("crate_textured", m_position);
	////TheObjMeshManager::Instance()->Translate("crate_textured", camPos);
	////TheObjMeshManager::Instance()->Scale("crate_textured", m_cellSize * 1.1f);
	////TheObjMeshManager::Instance()->Draw("crate_textured");


	//D3DXVECTOR3 a1Pos = a1.GetPosition();
	//D3DXVECTOR3 a2Pos = a2.GetPosition();
	//float rad = 3.0f;
	//float halfRad = rad * 0.5f;
	//float detectionRad = 30.0f;
	//float halfDetRad = detectionRad;

	//agentGroup.Update();

	////a1.Update();
	////a2.Update();
	//
	////if (
	////	((a1Pos.x + halfDetRad >= camPos.x - rad && a1Pos.x - halfDetRad <= camPos.x + rad) || 
	////	(a1Pos.x - halfDetRad <= camPos.x + rad && a1Pos.x + halfDetRad >= camPos.x + rad)) &&
	////	((a1Pos.z + halfDetRad >= camPos.z - rad && a1Pos.z - halfDetRad <= camPos.z + rad) || 
	////	(a1Pos.z - halfDetRad <= camPos.z + rad && a1Pos.z + halfDetRad >= camPos.z + rad))
	////	)
	////{
	////	a1.Update();
	////	a1.SetColour(D3DXVECTOR4(1.0f, 0.0f, 0.0f, 1.0f));
	////}
	////else
	////{
	////	a1.SetColour(D3DXVECTOR4(0.5f, 0.0f, 0.0f, 1.0f));
	////}

	////if (
	////	((a2Pos.x + halfDetRad >= camPos.x - rad && a2Pos.x - halfDetRad <= camPos.x + rad) || 
	////	(a2Pos.x - halfDetRad <= camPos.x + rad && a2Pos.x + halfDetRad >= camPos.x + rad)) &&
	////	((a2Pos.z + halfDetRad >= camPos.z - rad && a2Pos.z - halfDetRad <= camPos.z + rad) || 
	////	(a2Pos.z - halfDetRad <= camPos.z + rad && a2Pos.z + halfDetRad >= camPos.z + rad))
	////	)
	////{
	////	a2.Update();
	////	a2.SetColour(D3DXVECTOR4(0.0f, 1.0f, 0.0f, 1.0f));
	////}
	////else
	////{		
	////	a2.SetColour(D3DXVECTOR4(0.0f, 0.5f, 0.0f, 1.0f));
	////}

	//// a1 update
	//// find vector between a1 and a3
	//// if a1.pos + a1.r >= a3.pos + a3.r && a1.pos - r <= a3.pos + a3.r
	////  then slow down

	////if ((a1Pos.x + halfDetRad <= camPos.x - rad || a1Pos.x - halfDetRad >= camPos.x + rad) &&
	////	(a1Pos.z + halfDetRad <= camPos.z - rad || a1Pos.z - halfDetRad >= camPos.z + rad))
	////{
	////	// no need to check update a1Pos
	////	a1.SetColour(D3DXVECTOR4(0.5f, 0.0f, 0.0f, 1.0f));
	////}
	////else
	////{
	////	a1.Update();
	////	a1.SetColour(D3DXVECTOR4(1.0f, 0.0f, 0.0f, 1.0f));
	////}

	////
	////if ((a2Pos.x + halfDetRad <= camPos.x - rad || a2Pos.x - halfDetRad >= camPos.x + rad) &&
	////	(a2Pos.z + halfDetRad <= camPos.z - rad || a2Pos.z - halfDetRad >= camPos.z + rad))
	////{
	////	// no need to check update a1Pos
	////	a2.SetColour(D3DXVECTOR4(0.0f, 0.5f, 0.0f, 1.0f));
	////}
	////else
	////{
	////	a2.Update();
	////	a2.SetColour(D3DXVECTOR4(0.0f, 1.0f, 0.0f, 1.0f));
	////}

	//agentGroup.Draw();

	

	// draw detection range sphere

	//TheScreenManager::Instance()->EnableBlending();
	//
	//TheObjMeshManager::Instance()->SetColour("sphere", D3DXVECTOR4(1.0f, 0.0f, 0.0f, 0.2f));
	//TheObjMeshManager::Instance()->Translate("sphere", m_position);
	//TheObjMeshManager::Instance()->Translate("sphere", a1Pos);
	//TheObjMeshManager::Instance()->Scale("sphere", m_cellSize * (detectionRad * 0.1f));
	//TheObjMeshManager::Instance()->Draw("sphere");
	//
	//
	//TheObjMeshManager::Instance()->SetColour("sphere", D3DXVECTOR4(0.0f, 1.0f, 0.0f, 0.2f));
	//TheObjMeshManager::Instance()->Translate("sphere", m_position);
	//TheObjMeshManager::Instance()->Translate("sphere", a2Pos);
	//TheObjMeshManager::Instance()->Scale("sphere", m_cellSize * (detectionRad * 0.12f));
	//TheObjMeshManager::Instance()->Draw("sphere");
	//
	//TheScreenManager::Instance()->DisableBlending();
	
}

bool Maze::CheckCollision(OOBB3& oobb)
{
	//CalculateCurrentCell();
	D3DXVECTOR3 curPos = oobb.centre;
	float cellX, cellZ;
	curPos.x += m_cellSize.x * 0.5f; // need this if the maze size is odd
	curPos.z += m_cellSize.z * 0.5f;
	modf(curPos.x / m_cellSize.x, &cellX); // divide by cell size
	modf(curPos.z / m_cellSize.z, &cellZ);
	m_currentCell;
	CellPosition currentCell((int)cellX, (int)cellZ);

	D3DXVECTOR3 pos = oobb.centre;

	//TheScreenManager::Instance()->EnableBlending();
	//TheObjMeshManager::Instance()->SetColour("crate_textured", D3DXVECTOR4(1.0f, 1.0f, 1.0f, 0.5f));
	//TheObjMeshManager::Instance()->Translate("crate_textured", m_position);
	//D3DXVECTOR3 curCell3dPos = m_grid[currentCell].GetPos();
	//curCell3dPos.y += m_cellSize.y;
	//TheObjMeshManager::Instance()->Translate("crate_textured", curCell3dPos);
	//TheObjMeshManager::Instance()->Scale("crate_textured", m_cellSize * 0.5f);
	//TheObjMeshManager::Instance()->Draw("crate_textured");

	CellPosition cc = currentCell;
	bool collided = false;
	{
		CellPosition n(cc.first, cc.second - 1);
		CellPosition e(cc.first + 1, cc.second);
		CellPosition s(cc.first, cc.second + 1);
		CellPosition w(cc.first - 1, cc.second);

		D3DXVECTOR3 north = m_grid[n].GetOOBB().centre;
		D3DXVECTOR3 east = m_grid[e].GetOOBB().centre;
		D3DXVECTOR3 south = m_grid[s].GetOOBB().centre;
		D3DXVECTOR3 west = m_grid[w].GetOOBB().centre;

		//m_grid[n].GetOOBB().Draw();
		//m_grid[e].GetOOBB().Draw();
		//m_grid[s].GetOOBB().Draw();
		//m_grid[w].GetOOBB().Draw();

		float r = oobb.extents[0];

		TheScreenManager::Instance()->EnableBlending();
		if (m_grid[n].GetCellType() == EDGE || m_grid[n].GetCellType() == ROOM_EDGE ||
			m_grid[n].GetCellType() == WALL || m_grid[n].GetCellType() == ROOM_CORNER)
		{
			if (CheckCollisionOptimised(oobb, m_grid[n].GetOOBB()))
			{
				float f = (north.z + (m_cellSize.z * 0.5f)) - (pos.z - r);
				pos.z += f;

				//TheObjMeshManager::Instance()->SetColour("crate_textured", D3DXVECTOR4(1.0f, 1.0f, 1.0f, 0.5f));
				//TheObjMeshManager::Instance()->Translate("crate_textured", m_position);
				//D3DXVECTOR3 curCell3dPos = m_grid[n].GetPos();
				//curCell3dPos.y += m_cellSize.y;
				//TheObjMeshManager::Instance()->Translate("crate_textured", curCell3dPos);
				//TheObjMeshManager::Instance()->Scale("crate_textured", m_cellSize * 1.1f);
				//TheObjMeshManager::Instance()->Draw("crate_textured");

				collided = true;
			}
		}
		if (m_grid[e].GetCellType() == EDGE || m_grid[e].GetCellType() == ROOM_EDGE ||
			m_grid[e].GetCellType() == WALL || m_grid[e].GetCellType() == ROOM_CORNER)
		{
			if (CheckCollisionOptimised(oobb, m_grid[e].GetOOBB()))
			{
				float f = (east.x - (m_cellSize.x * 0.5f) - (pos.x + r));
				pos.x += f;

				//TheObjMeshManager::Instance()->SetColour("crate_textured", D3DXVECTOR4(1.0f, 1.0f, 1.0f, 0.5f));
				//TheObjMeshManager::Instance()->Translate("crate_textured", m_position);
				//D3DXVECTOR3 curCell3dPos = m_grid[e].GetPos();
				//curCell3dPos.y += m_cellSize.y;
				//TheObjMeshManager::Instance()->Translate("crate_textured", curCell3dPos);
				//TheObjMeshManager::Instance()->Scale("crate_textured", m_cellSize * 1.1f);
				//TheObjMeshManager::Instance()->Draw("crate_textured");
				//TheScreenManager::Instance()->DisableBlending();

				collided = true;
			}
		}
		if (m_grid[s].GetCellType() == EDGE || m_grid[s].GetCellType() == ROOM_EDGE ||
			m_grid[s].GetCellType() == WALL || m_grid[s].GetCellType() == ROOM_CORNER)
		{
			if (CheckCollisionOptimised(oobb, m_grid[s].GetOOBB()))
			{
				float f = (south.z - (m_cellSize.z * 0.5f)) - (pos.z + r);
				pos.z += f;

				//TheObjMeshManager::Instance()->SetColour("crate_textured", D3DXVECTOR4(1.0f, 1.0f, 1.0f, 0.5f));
				//TheObjMeshManager::Instance()->Translate("crate_textured", m_position);
				//D3DXVECTOR3 curCell3dPos = m_grid[s].GetPos();
				//curCell3dPos.y += m_cellSize.y;
				//TheObjMeshManager::Instance()->Translate("crate_textured", curCell3dPos);
				//TheObjMeshManager::Instance()->Scale("crate_textured", m_cellSize * 1.1f);
				//TheObjMeshManager::Instance()->Draw("crate_textured");

				collided = true;
			}
		}
		if (m_grid[w].GetCellType() == EDGE || m_grid[w].GetCellType() == ROOM_EDGE ||
			m_grid[w].GetCellType() == WALL || m_grid[w].GetCellType() == ROOM_CORNER)
		{
			if (CheckCollisionOptimised(oobb, m_grid[w].GetOOBB()))
			{
				float f = (west.x + (m_cellSize.x * 0.5f)) - (pos.x - r);
				pos.x += f;

				//TheObjMeshManager::Instance()->SetColour("crate_textured", D3DXVECTOR4(1.0f, 1.0f, 1.0f, 0.5f));
				//TheObjMeshManager::Instance()->Translate("crate_textured", m_position);
				//D3DXVECTOR3 curCell3dPos = m_grid[w].GetPos();
				//curCell3dPos.y += m_cellSize.y;
				//TheObjMeshManager::Instance()->Translate("crate_textured", curCell3dPos);
				//TheObjMeshManager::Instance()->Scale("crate_textured", m_cellSize * 1.1f);
				//TheObjMeshManager::Instance()->Draw("crate_textured");

				collided = true;
			}
		}
	}

	//{
	//	// corner cells
	//	CellPosition ne(cc.first + 1, cc.second - 1);
	//	CellPosition nw(cc.first - 1, cc.second + 1);
	//	CellPosition se(cc.first + 1, cc.second + 1);
	//	CellPosition sw(cc.first - 1, cc.second - 1);

	//	D3DXVECTOR3 northEast = m_grid[ne].GetOOBB().centre - oobb.centre;
	//	D3DXVECTOR3 northWest = m_grid[nw].GetOOBB().centre - oobb.centre;
	//	D3DXVECTOR3 southEast = m_grid[se].GetOOBB().centre - oobb.centre;
	//	D3DXVECTOR3 southWest = m_grid[sw].GetOOBB().centre - oobb.centre;

	//	float neLength = D3DXVec3Length(&northEast);
	//	float nwLength = D3DXVec3Length(&northWest);
	//	float seLength = D3DXVec3Length(&southEast);
	//	float swLength = D3DXVec3Length(&southWest);

	//	float totalRad = oobb.extents[0] + m_grid[ne].GetOOBB().extents[0];
	//	totalRad *= totalRad;

	//	m_grid[nw].GetOOBB().Draw();
	//	m_grid[ne].GetOOBB().Draw();
	//	m_grid[se].GetOOBB().Draw();
	//	m_grid[sw].GetOOBB().Draw();

	//	float r = sqrtf((oobb.extents[0] * oobb.extents[0]) + (oobb.extents[2] * oobb.extents[2]));
	//
	//	if (m_grid[ne].GetCellType() == EDGE || m_grid[ne].GetCellType() == ROOM_EDGE ||
	//		 m_grid[ne].GetCellType() == WALL || m_grid[ne].GetCellType() == ROOM_CORNER)
	//	{
	//		if (CheckCollisionOptimised(oobb, m_grid[ne].GetOOBB()))
	//		{
	//			float f = (northEast.z + (m_cellSize.z * 0.5f)) - (pos.z - r);				
	//			pos.z += f;
	//			TheObjMeshManager::Instance()->SetColour("crate_textured", D3DXVECTOR4(1.0f, 1.0f, 1.0f, 0.5f));
	//			TheObjMeshManager::Instance()->Translate("crate_textured", m_position);
	//			D3DXVECTOR3 curCell3dPos = m_grid[ne].GetPos();
	//			curCell3dPos.y += m_cellSize.y;
	//			TheObjMeshManager::Instance()->Translate("crate_textured", curCell3dPos);
	//			TheObjMeshManager::Instance()->Scale("crate_textured", m_cellSize * 1.1f);
	//			TheObjMeshManager::Instance()->Draw("crate_textured");
	//			collided = true;
	//		}
	//	}
	//	if (m_grid[nw].GetCellType() == EDGE || m_grid[nw].GetCellType() == ROOM_EDGE ||
	//		 m_grid[nw].GetCellType() == WALL || m_grid[nw].GetCellType() == ROOM_CORNER)
	//	{
	//		if (CheckCollisionOptimised(oobb, m_grid[nw].GetOOBB()))
	//		{
	//			float f = (northWest.x - (m_cellSize.x * 0.5f) - (pos.x + r));				
	//			pos.x += f;
	//			TheObjMeshManager::Instance()->SetColour("crate_textured", D3DXVECTOR4(1.0f, 1.0f, 1.0f, 0.5f));
	//			TheObjMeshManager::Instance()->Translate("crate_textured", m_position);
	//			D3DXVECTOR3 curCell3dPos = m_grid[nw].GetPos();
	//			curCell3dPos.y += m_cellSize.y;
	//			TheObjMeshManager::Instance()->Translate("crate_textured", curCell3dPos);
	//			TheObjMeshManager::Instance()->Scale("crate_textured", m_cellSize * 1.1f);
	//			TheObjMeshManager::Instance()->Draw("crate_textured");
	//			TheScreenManager::Instance()->DisableBlending();
	//			collided = true;
	//		}
	//	}
	//	if (m_grid[se].GetCellType() == EDGE || m_grid[se].GetCellType() == ROOM_EDGE ||
	//		 m_grid[se].GetCellType() == WALL || m_grid[se].GetCellType() == ROOM_CORNER)
	//	{
	//		if (CheckCollisionOptimised(oobb, m_grid[se].GetOOBB()))
	//		{
	//			float f = (southEast.z - (m_cellSize.z * 0.5f)) - (pos.z + r);
	//			pos.z += f;
	//			TheObjMeshManager::Instance()->SetColour("crate_textured", D3DXVECTOR4(1.0f, 1.0f, 1.0f, 0.5f));
	//			TheObjMeshManager::Instance()->Translate("crate_textured", m_position);
	//			D3DXVECTOR3 curCell3dPos = m_grid[se].GetPos();
	//			curCell3dPos.y += m_cellSize.y;
	//			TheObjMeshManager::Instance()->Translate("crate_textured", curCell3dPos);
	//			TheObjMeshManager::Instance()->Scale("crate_textured", m_cellSize * 1.1f);
	//			TheObjMeshManager::Instance()->Draw("crate_textured");
	//			collided = true;
	//		}
	//	}
	//	if (m_grid[sw].GetCellType() == EDGE || m_grid[sw].GetCellType() == ROOM_EDGE ||
	//		 m_grid[sw].GetCellType() == WALL || m_grid[sw].GetCellType() == ROOM_CORNER)
	//	{
	//		if (CheckCollisionOptimised(oobb, m_grid[sw].GetOOBB()))
	//		{
	//			float f = (southWest.x + (m_cellSize.x * 0.5f)) - (pos.x - r);
	//			pos.x += f;
	//			TheObjMeshManager::Instance()->SetColour("crate_textured", D3DXVECTOR4(1.0f, 1.0f, 1.0f, 0.5f));
	//			TheObjMeshManager::Instance()->Translate("crate_textured", m_position);
	//			D3DXVECTOR3 curCell3dPos = m_grid[sw].GetPos();
	//			curCell3dPos.y += m_cellSize.y;
	//			TheObjMeshManager::Instance()->Translate("crate_textured", curCell3dPos);
	//			TheObjMeshManager::Instance()->Scale("crate_textured", m_cellSize * 1.1f);
	//			TheObjMeshManager::Instance()->Draw("crate_textured");
	//			collided = true;
	//		}
	//	}
	//}

	oobb.centre = pos;
	TheScreenManager::Instance()->DisableBlending();
	return collided;
}

void Maze::DrawMiniMapColourPick()
{
	//std::vector<D3DXVECTOR4> colours;

	
	for (int i = 0; i != m_miniMapDrawCells.size(); i++)
	{
		//TheObjMeshManager::Instance()->SetColour("maze_floor", D3DXVECTOR4(m_cellColoursOp[it->first], 0.2f, 0.2f, 0.2f));
		D3DXVECTOR4 col = m_cellColoursOp[m_miniMapDrawCells[i]];
		//col.x /= 255.0f;
		//col.y /= 255.0f;
		//col.z /= 255.0f;
		col /= 255.0f;
		col.w = 1.0f;
		
		TheObjMeshManager::Instance()->Scale("crate_textured", m_miniMapElesScale);
		TheObjMeshManager::Instance()->SetColour("crate_textured", col);
		TheObjMeshManager::Instance()->Translate("crate_textured", m_position);
		D3DXVECTOR3 curCell3dPos = m_grid[m_miniMapDrawCells[i]].GetPos();
		//curCell3dPos.y += m_cellSize.y * 0.5f;
		TheObjMeshManager::Instance()->Translate("crate_textured", curCell3dPos);
		TheObjMeshManager::Instance()->Scale("crate_textured", m_cellSize);
		TheObjMeshManager::Instance()->Draw("crate_textured");
	}
	
	//colours.clear();
}

void Maze::DrawCameraPositionOrtho()
{
	// draw cam pos
	D3DXVECTOR3 camPos = TheCameraManager::Instance()->GetCameraPos();

	camPos.z += 10.0f;
	camPos.x += m_cellSize.x * (m_gridSize.x * 0.5f);
	camPos.z += m_cellSize.z * (m_gridSize.y * 0.5f) - m_cellSize.z;

	//camPos = m_grid[m_currentCell].GetPos();
	
	//TheObjMeshManager::Instance()->ChangeShader("maze_floor", "DefaultColour");
	TheObjMeshManager::Instance()->Scale("maze_floor", m_miniMapElesScale);
	TheObjMeshManager::Instance()->SetColour("maze_floor", D3DXVECTOR4(1.0f, 1.0f, 1.0f, 1.0f));
	TheObjMeshManager::Instance()->Translate("maze_floor", m_position);
	TheObjMeshManager::Instance()->Translate("maze_floor", camPos);
	TheObjMeshManager::Instance()->Scale("maze_floor", m_cellSize * 0.5f);
	TheObjMeshManager::Instance()->Draw("maze_floor");
	//TheObjMeshManager::Instance()->ChangeShader("maze_floor", "maze_floor_1");
}

void Maze::DrawMiniMapElements()
{
	CalculateCurrentCell();
	
	TheObjMeshManager::Instance()->ChangeShader("maze_floor", "DefaultColour");
	if (!TheMiniMap::Instance()->GetMapRendered())
	{
		TheScreenManager::Instance()->EnableBlending();
		for (int i = 0; i != m_miniMapDrawCells.size(); i++)
		{
			D3DXVECTOR3 curCell3dPos;
			
			TheObjMeshManager::Instance()->Scale("maze_floor", m_miniMapElesScale);
			TheObjMeshManager::Instance()->SetColour("maze_floor", D3DXVECTOR4(1.0f, 1.0f, 1.0f, 0.5f));
			TheObjMeshManager::Instance()->Translate("maze_floor", m_position);
			curCell3dPos = m_grid[m_miniMapDrawCells[i]].GetPos();
			TheObjMeshManager::Instance()->Translate("maze_floor", curCell3dPos);
			TheObjMeshManager::Instance()->Scale("maze_floor", m_cellSize);
			TheObjMeshManager::Instance()->Draw("maze_floor");

			//outline
			TheObjMeshManager::Instance()->Scale("maze_floor", m_miniMapElesScale);
			TheObjMeshManager::Instance()->SetColour("maze_floor", D3DXVECTOR4(0.0f, 0.0f, 0.0f, 1.0f));
			TheObjMeshManager::Instance()->Translate("maze_floor", m_position);
			curCell3dPos = m_grid[m_miniMapDrawCells[i]].GetPos();
			curCell3dPos.y -= 0.001f;
			TheObjMeshManager::Instance()->Translate("maze_floor", curCell3dPos);
			TheObjMeshManager::Instance()->Scale("maze_floor", m_cellSize * 1.7f);
			TheObjMeshManager::Instance()->Draw("maze_floor");
		}
		TheScreenManager::Instance()->DisableBlending();
		// draw current cell
		//CellType curCellType = m_grid[m_currentCell].GetCellType();
		//if (curCellType == ROOM || curCellType == PATH || curCellType == VERTICAL_DOOR ||
		//	curCellType == HORIZONTAL_DOOR)
		//{
		//	TheObjMeshManager::Instance()->SetColour("maze_floor", D3DXVECTOR4(0.0f, 0.0f, 0.7f, 0.5f));
		//	TheObjMeshManager::Instance()->Translate("maze_floor", m_position);
		//	D3DXVECTOR3 curCell3dPos = m_grid[m_currentCell].GetPos();
		//	curCell3dPos.y += m_cellSize.y;
		//	TheObjMeshManager::Instance()->Translate("maze_floor", curCell3dPos);
		//	TheObjMeshManager::Instance()->Scale("maze_floor", m_cellSize);
		//	TheObjMeshManager::Instance()->Draw("maze_floor");
		//}
	}
	else
	{
		DrawCameraPositionOrtho();

		//TheObjMeshManager::Instance()->ChangeShader("maze_floor", "DefaultTexture");
		//TheObjMeshManager::Instance()->ChangeTexture("maze_floor", 
		//	TheDX11TextureManager::Instance()->UseTexture(L"../../Assets/player_arrow.png"));

		//TheObjMeshManager::Instance()->SetColour("maze_floor", D3DXVECTOR4(0.0f, 1.0f, 1.0f, 1.0f));
		//TheObjMeshManager::Instance()->Translate("maze_floor", m_position);
		//TheObjMeshManager::Instance()->Translate("maze_floor", camPos);
		//TheObjMeshManager::Instance()->Rotate("maze_floor", TheCameraManager::Instance()->GetCameraRotation(),
		//													0.0f, 1.0f, 0.0f);
		//TheObjMeshManager::Instance()->Scale("maze_floor", m_cellSize * 10);
		//TheObjMeshManager::Instance()->Draw("maze_floor");
		//
		//TheObjMeshManager::Instance()->ChangeShader("maze_floor", "maze_floor_1");

		// draw minimap picked pos		
		D3DXVECTOR4 pickedColour = TheMiniMap::Instance()->GetPickedColour();

		if (pickedColour.x != -1.0f)
		{
			for (std::map<D3DXVECTOR4, CellPosition>::iterator colIt = m_cellColours.begin();
				colIt != m_cellColours.end(); ++colIt)
			{
				if (pickedColour.x == colIt->first.x)
				{
					if (pickedColour.y == colIt->first.y)
					{
						if (pickedColour.z == colIt->first.z)
						{
							TheObjMeshManager::Instance()->Scale("maze_floor", m_miniMapElesScale);
							TheObjMeshManager::Instance()->SetColour("maze_floor", D3DXVECTOR4(0.0f, 0.0f, 0.0f, 1.0f));
							TheObjMeshManager::Instance()->Translate("maze_floor", m_position);
							D3DXVECTOR3 curCell3dPos = m_grid[colIt->second].GetPos();
							curCell3dPos.y += 5.0f;
							TheObjMeshManager::Instance()->Translate("maze_floor", curCell3dPos);
							TheObjMeshManager::Instance()->Scale("maze_floor", m_cellSize);
							TheObjMeshManager::Instance()->Draw("maze_floor");
							break;
						}
					}
				}
			}
		}

		for (std::set<CellPosition>::iterator it = m_trail.begin(); it != m_trail.end(); ++it)
		{
			TheObjMeshManager::Instance()->Scale("maze_floor", m_miniMapElesScale);
			TheObjMeshManager::Instance()->SetColour("maze_floor", D3DXVECTOR4(0.0f, 1.0f, 0.0f, 1.0f));
			TheObjMeshManager::Instance()->Translate("maze_floor", m_position);
			D3DXVECTOR3 curCell3dPos = m_grid[*it].GetPos();
			curCell3dPos.y += 5.0f;
			TheObjMeshManager::Instance()->Translate("maze_floor", curCell3dPos);
			TheObjMeshManager::Instance()->Scale("maze_floor", m_cellSize * 0.5f);
			TheObjMeshManager::Instance()->Draw("maze_floor");
		}

		//TheObjMeshManager::Instance()->SetColour("maze_floor", D3DXVECTOR4(0.0f, 0.0f, 0.0f, 1.0f));
		//TheObjMeshManager::Instance()->Translate("maze_floor", m_position);
		//D3DXVECTOR3 pickedPos = m_grid[m_cellColours[m_pickedColour]].GetPos();
		//TheObjMeshManager::Instance()->Translate("maze_floor", pickedPos);
		//TheObjMeshManager::Instance()->Scale("maze_floor", m_cellSize * 0.5f);
		//TheObjMeshManager::Instance()->Draw("maze_floor");
	}
	TheObjMeshManager::Instance()->ChangeShader("maze_floor", "maze_floor_1");
}

void Maze::Update()
{
}

const D3DXVECTOR3& Maze::GetCellPos(const CellPosition& cp) const
{
	D3DXVECTOR3 pos = m_grid.find(cp)->second.GetPos();
	//D3DXVECTOR3 pos = m_grid[cp].GetPos();

	return pos;
}

RoomsCells& Maze::GetRoomCells()
{
	return m_roomCells;
}

void Maze::CalculateCurrentCell()
{
	D3DXVECTOR3 camPos = TheCameraManager::Instance()->GetCameraPos();
	float cellX, cellZ;
	//camPos.z -= m_cellSize.x * 0.5f;
	//camPos.x -= m_cellSize.z * 0.5f;
	modf(camPos.x / m_cellSize.x, &cellX); // divide by cell size
	modf(camPos.z / m_cellSize.z, &cellZ);

	//cellX /= 10.0f;
	//cellZ /= 10.0f;
	cellX += m_gridSize.x * 0.5f;
	cellZ += m_gridSize.y * 0.5f;
	CellPosition currentCell((int)cellX, (int)cellZ);

	if (cellX >= m_gridSize.x * 0.5f)
	{
		camPos.x += m_cellSize.x;
		modf(camPos.x / m_cellSize.x, &cellX);
		cellX += m_gridSize.x * 0.5f;
		currentCell.first = (int)cellX;
	}
	if (cellZ >= m_gridSize.y * 0.5f)
	{
		camPos.z += m_cellSize.z;
		modf(camPos.z / m_cellSize.z, &cellZ);
		cellZ += m_gridSize.y * 0.5f;
		currentCell.second = (int)cellZ;
	}

	m_currentCell = currentCell;
}

void Maze::CalculateCellsInVisibleRange()
{
	// TODO: wall cells
	// go through path/room cells and check if the north/east/south/west cells are in m_wallCells

	int visibleRange = 10;
	int checkRange = 7;
	std::vector<CellPosition> toCheckCells;

	for (int i = 1; i != checkRange; i++)
	{
		toCheckCells.push_back(CellPosition(m_currentCell.first, m_currentCell.second - i)); // north
		toCheckCells.push_back(CellPosition(m_currentCell.first + i, m_currentCell.second)); // east
		toCheckCells.push_back(CellPosition(m_currentCell.first, m_currentCell.second + i)); // south
		toCheckCells.push_back(CellPosition(m_currentCell.first - i, m_currentCell.second)); // west
	}

	//toCheckCells.push_back(CellPosition(m_currentCell.first, m_currentCell.second - 1)); // north
	//toCheckCells.push_back(CellPosition(m_currentCell.first + 1, m_currentCell.second)); // east
	//toCheckCells.push_back(CellPosition(m_currentCell.first, m_currentCell.second + 1)); // south
	//toCheckCells.push_back(CellPosition(m_currentCell.first - 1, m_currentCell.second)); // west

	//toCheckCells.push_back(CellPosition(m_currentCell.first, m_currentCell.second - 2)); // north
	//toCheckCells.push_back(CellPosition(m_currentCell.first + 2, m_currentCell.second)); // east
	//toCheckCells.push_back(CellPosition(m_currentCell.first, m_currentCell.second + 2)); // south
	//toCheckCells.push_back(CellPosition(m_currentCell.first - 2, m_currentCell.second)); // west
	
	// door cells
	toCheckCells.insert(toCheckCells.end(), m_doorsForDrawing.begin(), m_doorsForDrawing.end());

	//for (int i = 0; i != m_roomsCells.size(); i++)
	//{
	//	toCheckCells.insert(toCheckCells.end(), m_roomsCells[i].begin(), m_roomsCells[i].end());
	//}

	// check if current cell is within a room
	// if yes, then add room cells to toCheckCells
	//std::vector<CellPosition>::iterator roomIt;
	//for (int i = 0; i != m_roomsCells.size(); i++)
	//{
	//	roomIt = std::find(m_roomsCells[i].begin(), m_roomsCells[i].end(), m_currentCell);
	//	if (roomIt != m_roomsCells[i].end())
	//	{
	//		toCheckCells.insert(toCheckCells.end(), m_roomsCells[i].begin(), m_roomsCells[i].end());
	//	}
	//}

	Grid::iterator gridIt;

	//for (Grid::iterator it = m_grid.begin(); it != m_grid.end(); ++it)
	//{
	//	CellType curCellType = it->second.GetCellType();
	//	if (curCellType != EMPTY && curCellType != EDGE && curCellType != ROOM_EDGE && curCellType != ROOM_CORNER)
	//	{
	//		DrawWall(it->first);
	//	}
	//}

	for (int i = 0; i != toCheckCells.size(); i++)
	{
		// north
		for (int n = 0; n != visibleRange; n++)
		{
			CellPosition curCell = toCheckCells[i];

			// check north cells are in m_grid
			curCell.second -= n;
			gridIt = m_grid.find(curCell);
			if (gridIt != m_grid.end())
			{
				CellType curCellType = m_grid[curCell].GetCellType();

				if (curCellType != EMPTY && curCellType != EDGE && curCellType != ROOM_EDGE && curCellType != ROOM_CORNER)
				{
					if (curCellType == ROOM)
					{
					}
					else if (curCellType == WALL)
					{
						DrawWall(curCell);
					}
					else 
					{
						DrawCell(curCell);
					}
				}
				else
				{
					break;
				}
			}
		}

		// east
		for (int e = 0; e != visibleRange; e++)
		{
			CellPosition curCell = toCheckCells[i];

			curCell.first += e;
			gridIt = m_grid.find(curCell);
			if (gridIt != m_grid.end())
			{
				CellType curCellType = m_grid[curCell].GetCellType();
				if (curCellType != EMPTY && curCellType != EDGE && curCellType != ROOM_EDGE && curCellType != ROOM_CORNER)
				{
					if (curCellType == ROOM)
					{
					}
					else if (curCellType == WALL)
					{
						DrawWall(curCell);
					}
					else
					{
						DrawCell(curCell);
					}
				}
				else
				{
					break;
				}
			}
		}

		// south
		for (int s = 0; s != visibleRange; s++)
		{
			CellPosition curCell = toCheckCells[i];

			curCell.second += s;
			gridIt = m_grid.find(curCell);
			if (gridIt != m_grid.end())
			{
				CellType curCellType = m_grid[curCell].GetCellType();
				if (curCellType != EMPTY && curCellType != EDGE && curCellType != ROOM_EDGE && curCellType != ROOM_CORNER)
				{
					if (curCellType == ROOM)
					{
					}
					else if (curCellType == WALL)
					{
						DrawWall(curCell);
					}
					else
					{
						DrawCell(curCell);
					}
				}
				else
				{
					break;
				}
			}
		}

		// west 
		for (int w = 0; w != visibleRange; w++)
		{
			CellPosition curCell = toCheckCells[i];

			curCell.first -= w;
			gridIt = m_grid.find(curCell);
			if (gridIt != m_grid.end())
			{
				CellType curCellType = m_grid[curCell].GetCellType();

				if (curCellType != EMPTY && curCellType != EDGE && curCellType != ROOM_EDGE && curCellType != ROOM_CORNER)
				{
					if (curCellType == ROOM)
					{
					}
					else if (curCellType == WALL)
					{
						DrawWall(curCell);
					}
					else
					{
						DrawCell(curCell);
					}
				}
				else
				{
					break;
				}
			}
		}
	}
}

void Maze::DrawColourPick()
{
	if (m_canCheckForPick)
	{
		TheObjMeshManager::Instance()->ChangeShader("maze_floor", "DefaultColour");
		TheCameraManager::Instance()->Update();
		TheScreenManager::Instance()->GetDeviceContext()->OMSetRenderTargets(1, 
			TheScreenManager::Instance()->GetRenderTargetview(),
			TheScreenManager::Instance()->GetDepthStencilView());
		DX11::ClearColour(0.5f, 0.5f, 0.5f, 1.0f);
		
		//m_cellColours.clear();

		//int colourPickRange = 7; // max of 15
		//int colourStep = 1;
		//int currentColour = 1;
		//float colour255 = 1.0f / 255.0f;
		//D3DXVECTOR4 finalCol = D3DXVECTOR4(colour255, 0.0f, 0.0f, 1.0f);

		//CalculateCurrentCell();

		//CellPosition topLeft = CellPosition(int(m_currentCell.first - ((colourPickRange - 1) * 0.5f)), 
		//									int(m_currentCell.second - ((colourPickRange - 1) * 0.5f)));
		//CellPosition botRight = CellPosition(int(m_currentCell.first + ((colourPickRange - 1) * 0.5f)), 
		//									int(m_currentCell.second + ((colourPickRange - 1) * 0.5f)));

		//Grid::iterator it;
		//int xCounter = 0;
		//int yCounter = 0;
		//for (int x = topLeft.first; x <= botRight.first; x++)
		//{
		//	yCounter = 0;
		//	for (int y = topLeft.second; y <= botRight.second; y++)
		//	{
		//		CellPosition tempCell = CellPosition(topLeft.first + xCounter, topLeft.second + yCounter);
		//		it = m_grid.find(tempCell);
		//		if (it != m_grid.end())
		//		{
		//			if (it->second.GetCellType() != EMPTY && it->second.GetCellType() != EDGE)
		//			{
		//				TheObjMeshManager::Instance()->SetColour("crate_textured", finalCol);
		//				TheObjMeshManager::Instance()->Translate("crate_textured", m_position);
		//				D3DXVECTOR3 curCell3dPos = m_grid[tempCell].GetPos();
		//				TheObjMeshManager::Instance()->Translate("crate_textured", curCell3dPos);
		//				TheObjMeshManager::Instance()->Scale("crate_textured", m_cellSize);
		//				TheObjMeshManager::Instance()->Draw("crate_textured");
		//				m_cellColours[(float)currentColour] = tempCell;
		//				finalCol.x += colour255;
		//				currentColour += colourStep;
		//			}
		//		}
		//		yCounter++;
		//	}
		//	xCounter++;
		//}

		for (int i = 0; i != m_miniMapDrawCells.size(); i++)
		{
			CellType curCellType = m_grid[m_miniMapDrawCells[i]].GetCellType();

			if (curCellType == PATH)
			{
				D3DXVECTOR4 col = m_cellColoursOp[m_miniMapDrawCells[i]];
				col /= 255.0f;
				TheObjMeshManager::Instance()->Scale("maze_floor", m_miniMapElesScale);
				TheObjMeshManager::Instance()->SetColour("maze_floor", col);
				TheObjMeshManager::Instance()->Translate("maze_floor", m_position);
				D3DXVECTOR3 curCell3dPos = m_grid[m_miniMapDrawCells[i]].GetPos();
				//curCell3dPos.y += 5.0f;
				TheObjMeshManager::Instance()->Translate("maze_floor", curCell3dPos);
				TheObjMeshManager::Instance()->Scale("maze_floor", m_cellSize);
				TheObjMeshManager::Instance()->Draw("maze_floor");
			}
		}

		m_pickedColour = PickColourRGBA(D3DXVECTOR2((float)m_mouseX, (float)m_mouseY));
		TheObjMeshManager::Instance()->ChangeShader("maze_floor", "maze_floor_1");
	}
	else
	{
		m_pickedColour = D3DXVECTOR4(-1, -1, -1, -1);
	}
}

const D3DXVECTOR3& Maze::GetCellSize() const
{
	return m_cellSize;
}

const D3DXVECTOR2& Maze::GetGridSize() const
{
	return m_gridSize;
}

const D3DXVECTOR3& Maze::GetPos() const
{
	return m_position;
}

void Maze::OnKeyDownEvent(const WPARAM& event)
{
}

void Maze::OnKeyUpEvent(const WPARAM& event)
{
}

void Maze::OnMouseMotionEvent(const LPARAM& event)
{
	m_mouseX = LOWORD(event);
	m_mouseY = HIWORD(event);
//	m_canCheckForPick = !TheMiniMap::Instance()->GetCollided();
}

void Maze::OnMouseButtonDownEvent(const MSG& event)
{
	m_canCheckForPick = !TheMiniMap::Instance()->GetCollided();
}

void Maze::OnMouseButtonUpEvent(const MSG& event)
{
	m_canCheckForPick = false;
}

bool Maze::Load(File* f)
{
	int numOfRooms = -1;
	if (!f->GetD3DXVECTOR2(&m_gridSize))
	{
		DX11ErrorMsg(L"Expected D3DXVECTOR2", L"Maze::Load()", MB_OK);
		return false;
	}
	if (!f->GetD3DXVECTOR3(&m_cellSize))
	{
		DX11ErrorMsg(L"Expected m_cellSize", L"Maze::Load()", MB_OK);
		return false;
	}
	if (!f->GetInteger(&numOfRooms))
	{
		DX11ErrorMsg(L"Expected numOfRooms", L"Maze::Load()", MB_OK);
		return false;
	}
	if (numOfRooms > 0)
	{
		if (!f->GetRoomSizes(&m_sizeOfRooms))
		{
			DX11ErrorMsg(L"Error loading in room sizes", L"Maze::Load()", MB_OK);
			return false;
		}
	}
	else if (numOfRooms < 0)
	{
		DX11ErrorMsg(L"Cannot have negative amount of rooms", L"Maze::Load()", MB_OK);
	}
	
	if (!f->GetVectorConRooms(&m_connectingRooms))
	{
		DX11ErrorMsg(L"Error loading in connecting rooms", L"Maze::Load()", MB_OK);
	}

	for (int i = 0; i != m_sizeOfRooms.size(); i++)
	{
		m_sizeOfRooms[i].first += 2;
		m_sizeOfRooms[i].second += 2;
	}

	m_numOfRooms = numOfRooms;
	m_displayInfo.timeToGenerate = (float)GetTickCount();
	Generate(numOfRooms, m_gridSize, m_cellSize);
	m_displayInfo.timeToGenerate = GetTickCount() - m_displayInfo.timeToGenerate;

	TheConfigManager::Instance()->GetMazeGenTime(m_displayInfo.timeToGenerate);

	// set camera position
	// TODO: un hard code the room select
	D3DXVECTOR3 camPos = m_grid[m_roomsCells[0][10]].GetPos();
	camPos.x -= m_cellSize.x * (m_gridSize.x * 0.5f);
	camPos.z -= m_cellSize.z * (m_gridSize.y * 0.5f);
	
	//camPos.z -= 10.0f;
	camPos.y = 15.0f;
	TheCameraManager::Instance()->SetCameraPos(camPos);


	return true;
}

GameObject* CreateMaze()
{
	return new Maze();
}
static bool b = TheGameObjectFactory::Instance()->AddType("Maze", CreateMaze);

const char* Maze::GetTypeName() const
{
	return "Maze";
}